2 * Copyright (c) 2014 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
22 #if !GLIB_CHECK_VERSION (2, 31, 0)
23 #include <glib/gmacros.h>
26 #include "fido_privilege_checker.h"
27 #include "fido_asm_plugin_manager.h"
28 #include "fido_internal_types.h"
29 #include "fido_json_handler.h"
30 #include "fido_keys.h"
31 #include "fido_app_id_handler.h"
32 #include "fido_uaf_policy_checker.h"
33 #include "fido_selection_ui_adaptor.h"
34 #include "fido_logs.h"
35 #include "fido_uaf_types.h"
36 #include "fido-stub.h"
38 #define _FIDO_SERVICE_DBUS_PATH "/org/tizen/fido"
39 static guint owner_id = 0;
40 //GDBusObjectManagerServer *fido_dbus_mgr = NULL;
41 static Fido* fido_dbus_obj = NULL;
43 //TODO : current assumption is, ASM will handle multiple request queueing
45 typedef struct _dbus_info{
47 GDBusMethodInvocation *invocation;
50 typedef struct _discover_cb {
51 //fido_authenticator_cb cb;
53 _dbus_info_t *dbus_info;
56 typedef struct _fido_discover_asm_cb_data {
57 _fido_discover_asm_cb cb;
59 }_fido_discover_asm_cb_data_t;
62 _PROCESS_TYPE_MIN = 0,
66 _PROCESS_TYPE_CHECK_POLICY,
70 typedef struct _process_cb_data {
73 void *asm_in;/* ASM input data, type varies depending on operation name */
74 _dbus_info_t *dbus_info;
77 static void __process_dereg_queue(_dereg_q_t *dereg_q);
80 __create_empty_json_2d_array(void)
82 char **asm_resp_json_arr = calloc(1, sizeof(int));
84 char *empty_asm_resp = calloc(1, 128);
85 snprintf(empty_asm_resp, 127, "%s", _EMPTY_JSON_STRING);
86 asm_resp_json_arr[0] = empty_asm_resp;
88 return asm_resp_json_arr;
92 __free_2d_string_array(char **arr, int row_count)
94 RET_IF_FAIL_VOID(arr != NULL);
97 for (; i < row_count; i++)
104 __dup_string(const char *source)
107 return strdup(source);
113 __free_asm_discover_response_list_item(gpointer data)
115 RET_IF_FAIL_VOID(data != NULL);
117 _free_asm_discover_response((_asm_discover_response_t*)data);
121 __send_discover_response(Fido *object, GDBusMethodInvocation *invocation, int err, char **asm_resp_2d_arr, int asm_resp_len)
123 if (asm_resp_2d_arr == NULL
124 || asm_resp_len <= 0) {
126 char **empty_arr = __create_empty_json_2d_array();
127 fido_complete_fido_uaf_discover(object, invocation, err,
128 (const gchar * const*)empty_arr, 0);
130 __free_2d_string_array(empty_arr, 1);
134 fido_complete_fido_uaf_discover(object, invocation, err,
135 (const gchar * const*)asm_resp_2d_arr, asm_resp_len);
137 __free_2d_string_array(asm_resp_2d_arr, asm_resp_len);
141 _asm_get_info_cb(GList *asm_resp_list, void *user_data)
143 _INFO("_asm_get_info_cb");
145 _dbus_info_t *dbus_info = (_dbus_info_t *)user_data;
146 if (dbus_info != NULL) {
148 if (asm_resp_list != NULL) {
150 int str_list_len = g_list_length(asm_resp_list);
151 char **asm_resp_json_arr = calloc(str_list_len, sizeof(int));
155 GList *asm_resp_list_iter = g_list_first(asm_resp_list);
156 while (asm_resp_list_iter != NULL) {
157 _asm_discover_response_t *disc_resp = (_asm_discover_response_t*)(asm_resp_list_iter->data);
159 if (disc_resp->asm_response_json != NULL) {
160 asm_resp_json_arr[i++] = strdup(disc_resp->asm_response_json);
163 asm_resp_list_iter = g_list_next(asm_resp_list_iter);
166 __send_discover_response(dbus_info->dbus_obj, dbus_info->invocation, FIDO_ERROR_NONE,
167 asm_resp_json_arr, data_len);
170 __send_discover_response(dbus_info->dbus_obj, dbus_info->invocation, FIDO_ERROR_NOT_SUPPORTED,
174 if (asm_resp_list != NULL)
175 g_list_free_full(asm_resp_list, __free_asm_discover_response_list_item);
179 _send_process_response(_process_cb_data_t *cb_data, int tz_err_code, char *uaf_response_json)
181 _INFO("_send_process_response");
184 _dbus_info_t *dbus_info = (_dbus_info_t *)(cb_data->dbus_info);
185 if (dbus_info != NULL)
187 if (cb_data->type == _PROCESS_TYPE_CHECK_POLICY) {
188 _INFO("before fido_complete_fido_uaf_check_policy");
189 fido_complete_fido_uaf_check_policy(dbus_info->dbus_obj, dbus_info->invocation, tz_err_code);
193 _INFO("before fido_complete_fido_uaf_process_operation");
195 if (uaf_response_json != NULL)
196 fido_complete_fido_uaf_process_operation(dbus_info->dbus_obj, dbus_info->invocation, FIDO_ERROR_NONE,
199 fido_complete_fido_uaf_process_operation(dbus_info->dbus_obj, dbus_info->invocation, tz_err_code, _EMPTY_JSON_STRING);
203 SAFE_DELETE(uaf_response_json);
204 _free_message(cb_data->uaf_req);
206 SAFE_DELETE(cb_data->dbus_info);
208 if (cb_data->type == _PROCESS_TYPE_AUTH)
209 _free_fido_asm_auth_in((_fido_asm_auth_in_t*)(cb_data->asm_in));
210 else if (cb_data->type == _PROCESS_TYPE_REG)
211 _free_fido_asm_reg_in((_fido_asm_reg_in_t*)(cb_data->asm_in));
212 else if (cb_data->type == _PROCESS_TYPE_DEREG)
213 _free_fido_asm_dereg_in((_fido_asm_dereg_in_t*)(cb_data->asm_in));
215 SAFE_DELETE(cb_data->asm_in);
217 SAFE_DELETE(cb_data);
221 _discover_response_intermediate_cb(GList *asm_response_list, void *user_data)
223 _INFO("_discover_response_intermediate_cb");
225 _fido_discover_asm_cb_data_t *cb_data = (_fido_discover_asm_cb_data_t *)user_data;
227 int error = FIDO_ERROR_NONE;
228 GList *asm_auth_list = NULL;
230 if (asm_response_list == NULL)
231 _ERR("Discover response failed");
233 asm_auth_list = _uaf_parser_parse_asm_response_discover(asm_response_list, &error);
236 (cb_data->cb)(error, 0, asm_auth_list, cb_data->user_data);
238 if (asm_response_list != NULL)
239 g_list_free_full(asm_response_list, __free_asm_discover_response_list_item);
243 __fido_uaf_discover_internal(_fido_discover_asm_cb callback, void *user_data)
245 _INFO("__fido_uaf_discover_internal");
247 _fido_discover_asm_cb_data_t *cb_data_inter_mediate = (_fido_discover_asm_cb_data_t *) calloc(1, sizeof(_fido_discover_asm_cb_data_t));
248 cb_data_inter_mediate->cb = callback;
249 cb_data_inter_mediate->user_data = user_data;
251 return _asm_plugin_mgr_discover_all(_discover_response_intermediate_cb, cb_data_inter_mediate);
255 _asm_response_auth_process(int error_code, const char *asm_response_json, void *user_data)
257 _INFO("_asm_response_auth_process");
259 if (user_data == NULL)
260 _ERR("user_data is NULL");
262 _process_cb_data_t *cb_data = (_process_cb_data_t*)user_data;
263 if (cb_data == NULL) {
264 _ERR("_process_cb_data_t not found");
268 _INFO("error_code = [%d]", error_code);
270 if (error_code != 0) {
271 _ERR("ASM response contains error code [%d]", error_code);
272 _send_process_response((_process_cb_data_t *)user_data, error_code, NULL);
276 _asm_out_t *asm_out = NULL;
278 _INFO("before _uaf_parser_parse_asm_response_auth");
281 asm_out = _uaf_parser_parse_asm_response_auth(asm_response_json, &parser_err);
282 if (parser_err != 0 || asm_out == NULL) {
283 _ERR("_uaf_parser_parse_asm_response_auth failed");
285 int uaf_err_code = _convert_asm_status_code_to_uaf_error(parser_err);
286 if (uaf_err_code == FIDO_ERROR_NONE)
287 _send_process_response(cb_data, FIDO_ERROR_PROTOCOL_ERROR, NULL);
289 _send_process_response(cb_data, uaf_err_code, NULL);
291 _free_asm_out(asm_out);
297 _asm_auth_out_t *asm_auth_out = (_asm_auth_out_t*)(asm_out->response_data);
299 _fido_asm_auth_in_t *asm_auth_in = (_fido_asm_auth_in_t *) cb_data->asm_in;
301 _message_t *uaf_message = cb_data->uaf_req;
303 _op_header_t *header = uaf_message->header;
305 char *uaf_response_json = NULL;
308 /* TODO : Add logic to accumulate multiple auth response and form the assertion_list*/
309 GList *assertion_list = NULL;
311 _auth_reg_assertion_t *asst_data = (_auth_reg_assertion_t*)calloc(1, sizeof(_auth_reg_assertion_t));
313 _INFO("before assertion");
314 asst_data->assertion = strdup(asm_auth_out->assertion);
316 _INFO("before assertion_schm");
317 asst_data->assertion_schm = strdup(asm_auth_out->assertion_scheme);
319 assertion_list = g_list_append(assertion_list, asst_data);
321 assertion_list = g_list_first(assertion_list);
324 _INFO("before _uaf_composer_compose_uaf_process_response_auth");
325 parser_err = _uaf_composer_compose_uaf_process_response_auth(header, asm_auth_in->final_challenge,
326 assertion_list, &uaf_response_json);
328 g_list_free_full(assertion_list, _free_auth_reg_assertion_list_item);
330 _free_asm_out(asm_out);
333 if (parser_err != 0) {
334 _ERR("_uaf_composer_compose_uaf_process_response_auth failed");
335 _send_process_response((_process_cb_data_t *)user_data, FIDO_ERROR_INVALID_PARAMETER, NULL);
339 _send_process_response(cb_data, FIDO_ERROR_NONE, uaf_response_json);
343 _asm_response_reg_process(int error_code, const char *asm_response_json, void *user_data)
345 _INFO("_asm_response_reg_process");
347 _process_cb_data_t *cb_data = (_process_cb_data_t*)user_data;
351 if (error_code != 0) {
352 _ERR("ASM response contains error code [%d]", error_code);
354 _send_process_response((_process_cb_data_t *)user_data, error_code, NULL);
359 _asm_out_t *asm_out = NULL;
361 asm_out = _uaf_parser_parse_asm_response_reg(asm_response_json, &parser_err);
362 if (parser_err != 0 || asm_out == NULL) {
363 _ERR("_uaf_parser_parse_asm_response_reg failed");
365 int uaf_err_code = _convert_asm_status_code_to_uaf_error(parser_err);
366 if (uaf_err_code == FIDO_ERROR_NONE)
367 _send_process_response((_process_cb_data_t *)user_data, FIDO_ERROR_PROTOCOL_ERROR, NULL);
369 _send_process_response((_process_cb_data_t *)user_data, uaf_err_code, NULL);
371 _free_asm_out(asm_out);
376 _asm_reg_out_t *asm_reg_out = (_asm_reg_out_t*)(asm_out->response_data);
378 _fido_asm_reg_in_t *asm_reg_in = (_fido_asm_reg_in_t *)(cb_data->asm_in);
380 _message_t *uaf_req = cb_data->uaf_req;
381 _op_header_t *header = uaf_req->header;
383 char *uaf_response_json = NULL;
385 /* TODO : Add logic to accumulate multiple auth response and form the assertion_list*/
386 _auth_reg_assertion_t *ass_data = (_auth_reg_assertion_t*) calloc(1, sizeof(_auth_reg_assertion_t));
387 ass_data->assertion = __dup_string(asm_reg_out->assertion);
388 ass_data->assertion_schm = __dup_string(asm_reg_out->assertion_schm);
391 _free_asm_out(asm_out);
394 GList *ass_list = NULL;
395 ass_list = g_list_append(ass_list, ass_data);
397 parser_err = _uaf_composer_compose_uaf_process_response_reg(header, asm_reg_in->final_challenge,
398 ass_list, &uaf_response_json);
400 g_list_free_full(ass_list, _free_auth_reg_assertion_list_item);
402 if (parser_err != 0) {
403 _ERR("_uaf_composer_compose_uaf_process_response_reg failed");
404 _send_process_response((_process_cb_data_t *)user_data, FIDO_ERROR_INVALID_PARAMETER, NULL);
408 _send_process_response((_process_cb_data_t *)user_data, FIDO_ERROR_NONE, uaf_response_json);
412 __handle_reg(_process_cb_data_t *cb_data, _matched_auth_data_t *matched_auth)
416 _message_t *uaf_req = (_message_t *)(cb_data->uaf_req);
418 _reg_request_t *uaf_reg_req = (_reg_request_t *)(cb_data->uaf_req->data);
420 _fido_asm_reg_in_t *reg_in = (_fido_asm_reg_in_t*) calloc(1, sizeof(_fido_asm_reg_in_t));
422 /*If no app-id mentioned in UAF request*/
423 if (cb_data->uaf_req->header->app_id == NULL) {
424 if (cb_data->uaf_req->facet_id == NULL) {
425 _ERR("Failed to get app id");
426 _send_process_response(cb_data, FIDO_ERROR_UNTRUSTED_FACET_ID, NULL);
427 _free_fido_asm_reg_in(reg_in);
431 cb_data->uaf_req->header->app_id = strdup(cb_data->uaf_req->facet_id);
432 reg_in->app_id = strdup(cb_data->uaf_req->header->app_id);
436 reg_in->app_id = strdup(cb_data->uaf_req->header->app_id);
440 if (uaf_reg_req->user_name != NULL)
441 reg_in->user_name = strdup(uaf_reg_req->user_name);
445 char *fc_json = _uaf_composer_compose_final_challenge(reg_in->app_id, uaf_reg_req->challenge,
446 uaf_req->facet_id, cb_data->uaf_req->channel_binding);
448 if (fc_json == NULL) {
449 _ERR("Failed to compose final challenge");
450 _send_process_response(cb_data, FIDO_ERROR_PROTOCOL_ERROR, NULL);
451 _free_fido_asm_reg_in(reg_in);
456 /* Final challenge */
457 reg_in->final_challenge = fc_json;
459 int auth_idx_int = -1;
460 sscanf(matched_auth->auth_index, "%d", &auth_idx_int);
462 reg_in->attestation_type = matched_auth->att_type;
464 _version_t *version = (_version_t *)calloc(1, sizeof(_version_t));
465 version->major = _VERSION_MAJOR;
466 version->minor = _VERSION_MINOR;
468 char *asm_req_json = NULL;
470 cb_data->asm_in = reg_in;
473 int ret = _uaf_composer_compose_asm_reg_request(version, auth_idx_int, reg_in, &asm_req_json);
474 if (ret == 0 && asm_req_json != NULL)
475 _asm_ipc_send(matched_auth->asm_id,
476 asm_req_json, _asm_response_reg_process, cb_data);
478 _send_process_response(cb_data, FIDO_ERROR_PROTOCOL_ERROR, NULL);
480 SAFE_DELETE(asm_req_json);
481 SAFE_DELETE(version);
486 __copy_convert_uaf_trans_list(GList *uaf_tr_list)
488 RET_IF_FAIL(uaf_tr_list != NULL, NULL);
490 GList *asm_tr_list = NULL;
492 GList *uaf_tr_list_iter = g_list_first(uaf_tr_list);
493 while (uaf_tr_list_iter != NULL) {
495 _auth_transaction_t *uaf_tr = (_auth_transaction_t*)(uaf_tr_list_iter->data);
497 _fido_asm_transaction_t *asm_tr = calloc(1, sizeof(_fido_asm_transaction_t));
499 asm_tr->content = __dup_string(uaf_tr->content);
500 asm_tr->content_type = __dup_string(uaf_tr->content_type);
501 if (uaf_tr->display_charac != NULL) {
502 asm_tr->display_charac = calloc(1, sizeof(_fido_asm_display_png_characteristics_descriptor_t));
504 asm_tr->display_charac->bit_depth = uaf_tr->display_charac->bit_depth;
505 asm_tr->display_charac->color_type = uaf_tr->display_charac->color_type;
506 asm_tr->display_charac->compression = uaf_tr->display_charac->compression;
507 asm_tr->display_charac->filter = uaf_tr->display_charac->filter;
508 asm_tr->display_charac->height = uaf_tr->display_charac->height;
509 asm_tr->display_charac->interlace = uaf_tr->display_charac->interlace;
510 asm_tr->display_charac->width = uaf_tr->display_charac->width;
512 if (uaf_tr->display_charac->plte != NULL) {
514 GList *uaf_plte_iter = g_list_first(uaf_tr->display_charac->plte);
515 while (uaf_plte_iter != NULL) {
516 fido_rgb_pallette_entry_s *uaf_plte_entry = (fido_rgb_pallette_entry_s*)(uaf_plte_iter->data);
518 fido_rgb_pallette_entry_s *asm_plte_entry = calloc(1, sizeof(fido_rgb_pallette_entry_s));
519 asm_plte_entry->r = uaf_plte_entry->r;
520 asm_plte_entry->g = uaf_plte_entry->g;
521 asm_plte_entry->b = uaf_plte_entry->b;
523 asm_tr->display_charac->plte = g_list_append(asm_tr->display_charac->plte, asm_plte_entry);
525 uaf_plte_iter = uaf_plte_iter->next;
530 asm_tr_list = g_list_append(asm_tr_list, asm_tr);
532 uaf_tr_list_iter = uaf_tr_list_iter->next;
535 if (asm_tr_list != NULL) {
536 asm_tr_list = g_list_first(asm_tr_list);
537 _INFO("Trans list = [%d]", g_list_length(asm_tr_list));
543 __copy_string_list(GList *src)
547 RET_IF_FAIL(src != NULL, NULL);
551 GList *iter = g_list_first(src);
552 while (iter != NULL) {
553 char *str = (char*)(iter->data);
554 dest = g_list_append(dest, strdup(str));
565 __handle_auth(_process_cb_data_t *cb_data, _matched_auth_data_t *matched_auth)
567 _INFO("__handle_auth");
569 _auth_request_t *uaf_auth_req = (_auth_request_t*)(cb_data->uaf_req->data);
571 _fido_asm_auth_in_t *auth_asm_in = (_fido_asm_auth_in_t*)calloc(1, sizeof(_fido_asm_auth_in_t));
573 if (cb_data->uaf_req->header->app_id == NULL) {
575 if (cb_data->uaf_req->facet_id == NULL) {
576 _ERR("Failed to get app id");
577 _send_process_response(cb_data, FIDO_ERROR_PERMISSION_DENIED, NULL);
578 _free_fido_asm_auth_in(auth_asm_in);
581 cb_data->uaf_req->header->app_id = strdup(cb_data->uaf_req->facet_id);
582 auth_asm_in->app_id = strdup(cb_data->uaf_req->facet_id);
585 auth_asm_in->app_id = strdup(cb_data->uaf_req->header->app_id);
588 char *fc_json = _uaf_composer_compose_final_challenge(cb_data->uaf_req->header->app_id,
589 uaf_auth_req->challenge, cb_data->uaf_req->facet_id,
590 cb_data->uaf_req->channel_binding);
591 if (fc_json == NULL) {
592 _ERR("Failed to compose final challenge");
593 _send_process_response(cb_data, FIDO_ERROR_PROTOCOL_ERROR, NULL);
595 _free_fido_asm_auth_in(auth_asm_in);
600 auth_asm_in->key_ids = __copy_string_list(matched_auth->key_ids);
602 /* Final challenge */
603 auth_asm_in->final_challenge = fc_json;
606 auth_asm_in->trans_list = __copy_convert_uaf_trans_list(uaf_auth_req->transaction_list);
609 cb_data->asm_in = auth_asm_in;
611 char *asm_req_json = NULL;
612 _version_t *version = (_version_t *)calloc(1, sizeof(_version_t));
613 version->major = _VERSION_MAJOR;
614 version->minor = _VERSION_MINOR;
616 int auth_idx_int = -1;
617 sscanf(matched_auth->auth_index, "%d", &auth_idx_int);
618 if (auth_idx_int == -1) {
619 _ERR("ASM in data missing");
620 _send_process_response(cb_data, FIDO_ERROR_NO_SUITABLE_AUTHENTICATOR, NULL);
622 _free_fido_asm_auth_in(auth_asm_in);
623 SAFE_DELETE(version);
628 int ret = _uaf_composer_compose_asm_auth_request(version, auth_idx_int, auth_asm_in, &asm_req_json);
629 if (ret == 0 && asm_req_json != NULL) {
630 _asm_ipc_send(matched_auth->asm_id,
631 asm_req_json, _asm_response_auth_process, cb_data);
634 _send_process_response(cb_data, FIDO_ERROR_INVALID_PARAMETER, NULL);
637 SAFE_DELETE(version);
638 SAFE_DELETE(asm_req_json);
642 _ui_response_callback(int error_code, _ui_auth_data_t *selected_auth_data, void *user_data)
644 if (selected_auth_data == NULL) {
645 _ERR("User did not select any Authenticator");
646 _send_process_response((_process_cb_data_t *)user_data, error_code, NULL);
647 free(selected_auth_data);
651 _INFO("User selected [%s] authenticator index", selected_auth_data->auth_index);
653 _process_cb_data_t *cb_data = (_process_cb_data_t*)user_data;
656 _matched_auth_data_t *match_data = (_matched_auth_data_t*)calloc(1, sizeof(_matched_auth_data_t));
657 match_data->att_type = selected_auth_data->att_type;
658 match_data->auth_index = selected_auth_data->auth_index;
659 match_data->asm_id = strdup(selected_auth_data->asm_id);
661 if (cb_data->type == _PROCESS_TYPE_REG)
662 __handle_reg(cb_data, match_data);
664 if (cb_data->type == _PROCESS_TYPE_AUTH)
665 __handle_auth(cb_data, match_data);
667 _free_matched_auth_data(match_data);
672 _asm_response_dereg_process(int error_code, const char *asm_response_json, void *user_data)
674 _dereg_q_t *dereg_q = (_dereg_q_t*)(user_data);
675 _process_cb_data_t *cb_data = (_process_cb_data_t*)(dereg_q->cb_data);
680 /*Process next dereg*/
681 GQueue *q = (GQueue*) (dereg_q->dereg_asm_in_q);
682 if (g_queue_is_empty(q) == FALSE)
683 __process_dereg_queue(user_data);
685 /*ASM does not return success/faliure for dereg*/
686 _INFO("Ignoring ASM's response for dereg");
687 _send_process_response((_process_cb_data_t *)cb_data, FIDO_ERROR_NONE, NULL);
689 _INFO("Deleting dereg_asm_in_q");
690 /*Elements were deleted during pop*/
691 g_queue_free(dereg_q->dereg_asm_in_q);
692 dereg_q->dereg_asm_in_q = NULL;
693 _INFO("After Deleting dereg_asm_in_q");
699 __process_dereg_queue(_dereg_q_t *dereg_q)
701 _INFO("__process_dereg_queue");
703 GQueue *q = dereg_q->dereg_asm_in_q;
707 if (g_queue_is_empty(q) == true) {
708 _INFO("Deleting dereg_asm_in_q");
709 g_queue_free(dereg_q->dereg_asm_in_q);
710 dereg_q->dereg_asm_in_q = NULL;
711 _INFO("After Deleting dereg_asm_in_q");
715 _process_cb_data_t *cb_data = (_process_cb_data_t*)(dereg_q->cb_data);
716 _message_t *uaf_message = cb_data->uaf_req;
718 _matched_auth_dereg_t *dereg_data = (_matched_auth_dereg_t*)(g_queue_pop_head(q));
720 char *asm_req_json = NULL;
722 int auth_index_int = _INVALID_INT;
723 sscanf(dereg_data->auth_index, "%d", &auth_index_int);
725 _INFO("Auth index for dereg req = [%d]", auth_index_int);
727 int ret = _uaf_composer_compose_asm_dereg_request(uaf_message->header->version, auth_index_int,
728 dereg_data, &asm_req_json);
730 /*TODO : ASM does not return anything for dereg, so do not wait for response, send back
733 if (ret == 0 && asm_req_json != NULL) {
734 _asm_ipc_send(dereg_data->asm_id,
735 asm_req_json, _asm_response_dereg_process, dereg_q);
738 _send_process_response(cb_data, FIDO_ERROR_INVALID_PARAMETER, NULL);
741 _free_matched_auth_dereg(dereg_data);
742 SAFE_DELETE(asm_req_json);
747 __get_keyid_list_from_app_reg(GList *app_reg_list)
749 _INFO("__get_keyid_list_from_app_reg");
751 RET_IF_FAIL(app_reg_list != NULL, NULL);
753 GList *key_id_list = NULL;
755 GList *app_reg_list_iter = g_list_first(app_reg_list);
756 while (app_reg_list_iter != NULL) {
758 _asm_app_reg_t *app_reg = (_asm_app_reg_t*)(app_reg_list_iter->data);
759 if (app_reg != NULL) {
761 if (app_reg->key_id_list != NULL) {
762 GList *key_id_list_iter = g_list_first(app_reg->key_id_list);
763 while (key_id_list_iter != NULL) {
764 char *key_id = (char*)(key_id_list_iter->data);
765 if (key_id != NULL) {
766 key_id_list = g_list_append(key_id_list, strdup(key_id));
767 _INFO("[%s]", key_id);
770 key_id_list_iter = key_id_list_iter->next;
775 app_reg_list_iter = app_reg_list_iter->next;
782 __get_auth_list_with_keyids(GList *available_authenticators)
784 _INFO("__get_auth_list_with_keyids");
786 GList *available_authenticators_full = NULL;
788 GList *avl_auth_iter = g_list_first(available_authenticators);
789 while (avl_auth_iter != NULL) {
791 fido_authenticator_s *asm_auth = (fido_authenticator_s*)(avl_auth_iter->data);
792 if (asm_auth != NULL) {
793 char *get_reg_json = _uaf_composer_compose_get_registrations_request(asm_auth->auth_index);
794 char *get_reg_resp = _asm_ipc_send_sync(asm_auth->asm_id, get_reg_json);
796 if (get_reg_resp != NULL)
797 _INFO("_asm_ipc_send_sync = [%s]", get_reg_resp);
799 _asm_get_reg_out_t *get_reg_out = _uaf_parser_parser_asm_get_reg_response(get_reg_resp);
800 if (get_reg_out != NULL) {
801 asm_auth->key_ids = __get_keyid_list_from_app_reg(get_reg_out->app_reg_list);
802 asm_auth->key_ids = g_list_first(asm_auth->key_ids);
803 _INFO(" asm_auth->key_ids count = [%d]", g_list_length(asm_auth->key_ids));
805 available_authenticators_full = g_list_append(available_authenticators_full, asm_auth);
807 SAFE_DELETE(get_reg_json);
808 SAFE_DELETE(get_reg_resp);
809 _free_asm_get_reg_out(get_reg_out);
812 avl_auth_iter = avl_auth_iter->next;
815 return available_authenticators_full;
819 __free_matched_dereg_auth_data_list_item(gpointer data)
821 RET_IF_FAIL_VOID(data != NULL);
823 _free_matched_auth_dereg((_matched_auth_dereg_t*)data);
827 _discover_response_cb_for_process(int tz_error_code, int error_code, GList *available_authenticators, void *user_data)
829 _INFO("_discover_response_cb_for_process [%p]", user_data);
831 _process_cb_data_t *cb_data = (_process_cb_data_t*)user_data;
833 if (tz_error_code != FIDO_ERROR_NONE) {
834 _ERR("Failed to get available authenticator info [%d]", tz_error_code);
835 _send_process_response(cb_data, FIDO_ERROR_NOT_SUPPORTED, NULL);
839 if (available_authenticators == NULL) {
840 _ERR("No supported authenticators found");
841 _send_process_response(cb_data, FIDO_ERROR_NO_SUITABLE_AUTHENTICATOR, NULL);
845 _INFO("cb_data->type = [%d]", cb_data->type);
847 GList *available_authenticators_full = g_list_first(available_authenticators);
849 if (cb_data->type == _PROCESS_TYPE_CHECK_POLICY) {
851 _INFO("_PROCESS_TYPE_CHECK_POLICY");
853 if (cb_data->uaf_req->header->operation != NULL)
854 _INFO("operation = [%s]", cb_data->uaf_req->header->operation);
856 _ERR("operation = [NULL]");
858 if ((strcmp(cb_data->uaf_req->header->operation, _UAF_OPERATION_NAME_KEY_REG) == 0)
859 || ((strcmp(cb_data->uaf_req->header->operation, _UAF_OPERATION_NAME_KEY_AUTH) == 0))) {
861 _policy_t *policy = NULL;
863 if (strcmp(cb_data->uaf_req->header->operation, _UAF_OPERATION_NAME_KEY_REG) == 0) {
864 _reg_request_t *uaf_reg_req = (_reg_request_t *)(cb_data->uaf_req->data);
865 policy = uaf_reg_req->policy;
866 _INFO("_PROCESS_TYPE_CHECK_POLICY for reg");
868 else if (strcmp(cb_data->uaf_req->header->operation, _UAF_OPERATION_NAME_KEY_AUTH) == 0) {
869 _auth_request_t *uaf_auth_req = (_auth_request_t *)(cb_data->uaf_req->data);
870 policy = uaf_auth_req->policy;
871 _INFO("_PROCESS_TYPE_CHECK_POLICY for auth");
874 if (policy->is_keyid_present == true) {
875 /*Available authenticators' keyIDs can be fetched via GetRegistrations ASM op*/
876 _INFO("Need to call GetRegistrations to match policy");
877 GList *avl_auth_list_full_temp = __get_auth_list_with_keyids(available_authenticators);
878 if (avl_auth_list_full_temp != NULL) {
879 g_list_free(available_authenticators_full);
881 available_authenticators_full = g_list_first(avl_auth_list_full_temp);
885 GList *allowed_auth_list = _policy_checker_get_matched_auth_list(policy, available_authenticators_full);
886 g_list_free_full(available_authenticators_full, _free_asm_auth_list);
888 if ((allowed_auth_list != NULL) && g_list_length(allowed_auth_list) > 0) {
890 _send_process_response(cb_data, FIDO_ERROR_NONE, NULL);
893 _send_process_response(cb_data, FIDO_ERROR_NO_SUITABLE_AUTHENTICATOR, NULL);
896 if (allowed_auth_list != NULL)
897 g_list_free_full(allowed_auth_list, _free_matched_auth_data);
900 else if (strcmp(cb_data->uaf_req->header->operation, _UAF_OPERATION_NAME_KEY_DE_REG) == 0) {
902 _dereg_request_t *dereg_req = (_dereg_request_t*)(cb_data->uaf_req->data);
904 /* _matched_auth_dereg_t list*/
905 if (cb_data->uaf_req->header->app_id == NULL)
906 cb_data->uaf_req->header->app_id = strdup(cb_data->uaf_req->facet_id);
908 GList *matched_auth_list = _policy_checker_get_matched_auth_list_dereg(cb_data->uaf_req->header->app_id, dereg_req->auth_info_list,
909 available_authenticators_full);
910 g_list_free_full(available_authenticators_full, _free_asm_auth_list);
912 if ((matched_auth_list != NULL) && g_list_length(matched_auth_list) > 0) {
914 _send_process_response(cb_data, FIDO_ERROR_NONE, NULL);
917 _send_process_response(cb_data, FIDO_ERROR_NO_SUITABLE_AUTHENTICATOR, NULL);
920 if (matched_auth_list != NULL)
921 g_list_free_full(matched_auth_list, __free_matched_dereg_auth_data_list_item);
927 if (cb_data->type == _PROCESS_TYPE_DEREG) {
930 _dereg_request_t *dereg_req = (_dereg_request_t*)(cb_data->uaf_req->data);
932 if (cb_data->uaf_req->header->app_id == NULL)
933 cb_data->uaf_req->header->app_id = strdup(cb_data->uaf_req->facet_id);
935 /* _matched_auth_dereg_t list*/
936 GList *matched_auth_list = _policy_checker_get_matched_auth_list_dereg(cb_data->uaf_req->header->app_id, dereg_req->auth_info_list,
937 available_authenticators_full);
939 g_list_free_full(available_authenticators_full, _free_asm_auth_list);
941 if (matched_auth_list == NULL){
942 _ERR("No supported authenticators found");
943 _send_process_response(cb_data, FIDO_ERROR_NO_SUITABLE_AUTHENTICATOR, NULL);
947 _dereg_q_t *dereg_q = (_dereg_q_t*) calloc(1, sizeof(_dereg_q_t));
949 GList *matched_auth_list_iter = g_list_first(matched_auth_list);
950 while (matched_auth_list_iter != NULL) {
951 _matched_auth_dereg_t *dereg_auth_matched = (_matched_auth_dereg_t*) (matched_auth_list_iter->data);
953 if (dereg_auth_matched != NULL) {
954 GQueue *q = dereg_q->dereg_asm_in_q;
957 dereg_q->dereg_asm_in_q = g_queue_new();
959 g_queue_push_head(dereg_q->dereg_asm_in_q, dereg_auth_matched);
961 matched_auth_list_iter = matched_auth_list_iter->next;
964 /*The elements will be deleted while freeing dereg_q->dereg_asm_in_q*/
965 g_list_free(matched_auth_list);
967 dereg_q->cb_data = cb_data;
969 __process_dereg_queue(dereg_q);
974 _policy_t *policy = NULL;
976 if (cb_data->type == _PROCESS_TYPE_REG) {
977 _reg_request_t *uaf_reg_req = (_reg_request_t *)(cb_data->uaf_req->data);
978 policy = uaf_reg_req->policy;
980 else if (cb_data->type == _PROCESS_TYPE_AUTH) {
981 _auth_request_t *uaf_auth_req = (_auth_request_t *)(cb_data->uaf_req->data);
982 policy = uaf_auth_req->policy;
985 _send_process_response(cb_data, FIDO_ERROR_UNKNOWN, NULL);
989 if (policy->is_keyid_present == true) {
990 /*Available authenticators' keyIDs can be fetched via GetRegistrations ASM op*/
991 _INFO("Need to call GetRegistrations to match policy");
992 GList *avl_auth_list_full_temp = __get_auth_list_with_keyids(available_authenticators);
993 if (avl_auth_list_full_temp != NULL) {
994 g_list_free(available_authenticators_full);
995 available_authenticators_full = g_list_first(avl_auth_list_full_temp);
1000 GList *allowed_auth_list = _policy_checker_get_matched_auth_list(policy, available_authenticators_full);
1001 g_list_free_full(available_authenticators_full, _free_asm_auth_list);
1003 if (allowed_auth_list == NULL){
1004 _ERR("No supported authenticators found");
1005 _send_process_response(cb_data, FIDO_ERROR_NO_SUITABLE_AUTHENTICATOR, NULL);
1011 allowed_auth_list = g_list_first(allowed_auth_list);
1013 if (g_list_length(allowed_auth_list) > 1) {
1016 GList *ui_data_list = NULL;
1018 GList *allowed_auth_list_iter = allowed_auth_list;
1019 while (allowed_auth_list_iter != NULL) {
1020 _matched_auth_data_t *match_data = (_matched_auth_data_t *)(allowed_auth_list_iter->data);
1022 if (match_data != NULL) {
1024 _ui_auth_data_t *ui_data = (_ui_auth_data_t*) calloc(1, sizeof(_ui_auth_data_t));
1025 if (match_data->asm_id != NULL)
1026 ui_data->asm_id = strdup(match_data->asm_id);
1028 _ERR("No ASM id found to send to UI!!");
1030 ui_data->auth_index = strdup(match_data->auth_index);
1031 ui_data->att_type = match_data->att_type;
1033 ui_data->label = strdup(match_data->label);
1035 ui_data_list = g_list_append(ui_data_list, ui_data);
1037 allowed_auth_list_iter = allowed_auth_list_iter->next;
1041 int ret = _auth_ui_selector_send(ui_data_list, _ui_response_callback, cb_data);
1043 _ERR("Failed to invoke selector UI");
1044 _send_process_response(cb_data, FIDO_ERROR_NOT_SUPPORTED, NULL);
1045 if (allowed_auth_list != NULL)
1046 g_list_free_full(allowed_auth_list, _free_matched_auth_data);
1052 GList *allowed_auth_list_iter = allowed_auth_list;
1053 _matched_auth_data_t *match_data = (_matched_auth_data_t *)(allowed_auth_list_iter->data);
1055 if (cb_data->type == _PROCESS_TYPE_REG)
1056 __handle_reg(cb_data, match_data);
1058 else if (cb_data->type == _PROCESS_TYPE_AUTH)
1059 __handle_auth(cb_data, match_data);
1062 if (allowed_auth_list != NULL)
1063 g_list_free_full(allowed_auth_list, _free_matched_auth_data);
1068 _handle_process_message(_process_cb_data_t *cb_data)
1070 return __fido_uaf_discover_internal(_discover_response_cb_for_process, cb_data);
1074 __facet_id_cb(int err, const char *facet_id, void *user_data)
1076 _INFO("__facet_id_cb");
1077 if (facet_id != NULL)
1078 _INFO("[%s]", facet_id);
1080 _process_cb_data_t *cb_data = (_process_cb_data_t*)user_data;
1082 if (err != FIDO_ERROR_NONE || facet_id == NULL) {
1083 _send_process_response(cb_data, err, NULL);
1087 cb_data->uaf_req->facet_id = strdup(facet_id);
1089 int error_code = FIDO_ERROR_NONE;
1091 if (cb_data->type != _PROCESS_TYPE_CHECK_POLICY) {
1094 * 1. Extract embedded policy to find the suitable authenticator(s)
1095 * 2. Show UI to let user select one, if (1) gives multiple result.
1096 * 3. Compose ASMRequest in json format
1097 * 4. Send the same to asm
1098 * 5. Send the ASMResponse to application.
1101 if (strcmp(cb_data->uaf_req->header->operation, _UAF_OPERATION_NAME_KEY_REG) == 0)
1102 cb_data->type = _PROCESS_TYPE_REG;
1104 else if (strcmp(cb_data->uaf_req->header->operation, _UAF_OPERATION_NAME_KEY_AUTH) == 0)
1105 cb_data->type = _PROCESS_TYPE_AUTH;
1107 else if (strcmp(cb_data->uaf_req->header->operation, _UAF_OPERATION_NAME_KEY_DE_REG) == 0)
1108 cb_data->type = _PROCESS_TYPE_DEREG;
1111 _send_process_response(cb_data, FIDO_ERROR_INVALID_PARAMETER, NULL);
1116 error_code = _handle_process_message(cb_data);
1118 if (error_code != FIDO_ERROR_NONE) {
1119 _send_process_response(cb_data, error_code, NULL);
1124 _dbus_on_fido_init(Fido *object, GDBusMethodInvocation *invocation)
1126 fido_complete_fido_uaf_init(object, invocation, FIDO_ERROR_NONE);
1132 _dbus_on_fido_deinit(Fido *object, GDBusMethodInvocation *invocation)
1134 if (is_allowed_to_call(invocation, _FIDO_CLIENT_PRIVILEGE) == false) {
1135 fido_complete_fido_uaf_deinit(object, invocation, FIDO_ERROR_PERMISSION_DENIED);
1138 //_auth_ui_selector_deinit();
1139 fido_complete_fido_uaf_deinit(object, invocation, FIDO_ERROR_NONE);
1146 _dbus_on_fido_discover(Fido *object, GDBusMethodInvocation *invocation)
1148 _INFO("_dbus_on_fido_discover");
1149 if (is_allowed_to_call(invocation, _FIDO_CLIENT_PRIVILEGE) == false) {
1151 __send_discover_response(object, invocation, FIDO_ERROR_PERMISSION_DENIED,
1156 _dbus_info_t *dbus_info = (_dbus_info_t *)calloc(1, sizeof(_dbus_info_t));
1157 dbus_info->dbus_obj = object;
1158 dbus_info->invocation = invocation;
1160 int ret = _asm_plugin_mgr_discover_all(_asm_get_info_cb, dbus_info);
1161 if (ret != FIDO_ERROR_NONE) {
1163 _ERR("_asm_ipc_send failed = [%d]", ret);
1164 __send_discover_response(dbus_info->dbus_obj, dbus_info->invocation, FIDO_ERROR_NOT_SUPPORTED,
1167 SAFE_DELETE(dbus_info);
1175 _dbus_handle_process_or_check_policy(Fido *object, GDBusMethodInvocation *invocation,
1176 const gchar *uaf_request_json, const gchar *channel_binding,
1177 _process_type_t type)
1180 _INFO("_dbus_handle_process_or_check_policy");
1182 _process_cb_data_t *cb_data = (_process_cb_data_t*) calloc(1, sizeof(_process_cb_data_t));
1183 _dbus_info_t *dbus_info = (_dbus_info_t *)calloc(1, sizeof(_dbus_info_t));
1184 dbus_info->dbus_obj = object;
1185 dbus_info->invocation = invocation;
1186 cb_data->dbus_info = dbus_info;
1187 cb_data->type = type;
1189 if (is_allowed_to_call(invocation, _FIDO_CLIENT_PRIVILEGE) == false) {
1190 _send_process_response(cb_data, FIDO_ERROR_PERMISSION_DENIED, NULL);
1194 if (uaf_request_json == NULL) {
1195 _send_process_response(cb_data, FIDO_ERROR_PROTOCOL_ERROR, NULL);
1199 _INFO("%s", uaf_request_json);
1201 _message_t *uaf_message = _uaf_parser_parse_message(uaf_request_json, channel_binding);
1202 if (uaf_message == NULL) {
1203 _send_process_response(cb_data, FIDO_ERROR_PROTOCOL_ERROR, NULL);
1208 cb_data->uaf_req = uaf_message;
1211 int ret = _verify_and_get_facet_id(uaf_message->header->app_id, invocation, __facet_id_cb, cb_data);
1212 if (ret != FIDO_ERROR_NONE) {
1213 _send_process_response(cb_data, FIDO_ERROR_UNTRUSTED_FACET_ID, NULL);
1221 _dbus_on_fido_uaf_is_supported(Fido *object, GDBusMethodInvocation *invocation,
1222 const gchar *uaf_request_json)
1224 _INFO("_dbus_on_fido_uaf_is_supported");
1226 return _dbus_handle_process_or_check_policy(object, invocation, uaf_request_json, NULL,
1227 _PROCESS_TYPE_CHECK_POLICY);
1231 _dbus_on_fido_process_operation(Fido *object, GDBusMethodInvocation *invocation,
1232 const gchar *uaf_request_json, const gchar* channel_binding_json)
1234 _INFO("_dbus_on_fido_process_operation");
1236 return _dbus_handle_process_or_check_policy(object, invocation, uaf_request_json,
1237 channel_binding_json, _PROCESS_TYPE_MIN);
1241 _dbus_on_fido_uaf_notify_result(Fido *object, GDBusMethodInvocation *invocation, const gchar *arg_cookie, gint arg_respose_code,
1242 const gchar *uaf_response_json)
1244 fido_complete_fido_uaf_notify_result(object, invocation, 0, 0);
1249 on_bus_acquired (GDBusConnection *connection, const gchar *name, gpointer user_data)
1251 dlog_print(DLOG_INFO, "FIDO", "on_bus_acquired");
1253 _INFO("on_bus_acquired [%s]", name);
1255 GDBusInterfaceSkeleton* interface = NULL;
1256 fido_dbus_obj = fido_skeleton_new();
1257 if (fido_dbus_obj == NULL) {
1258 _ERR("fido_dbus_obj NULL!!");
1262 dlog_print(DLOG_INFO, "FIDO", "G_DBUS_INTERFACE_SKELETON");
1264 interface = G_DBUS_INTERFACE_SKELETON(fido_dbus_obj);
1265 if (!g_dbus_interface_skeleton_export(interface, connection, _FIDO_SERVICE_DBUS_PATH, NULL)) {
1266 _ERR("export failed!!");
1270 dlog_print(DLOG_INFO, "FIDO", "g_signal_connect");
1272 _INFO("connecting fido signals start");
1274 g_signal_connect(fido_dbus_obj, "handle_fido_uaf_init",
1275 G_CALLBACK(_dbus_on_fido_init), NULL);
1277 g_signal_connect(fido_dbus_obj, "handle_fido_uaf_deinit",
1278 G_CALLBACK(_dbus_on_fido_deinit), NULL);
1280 g_signal_connect(fido_dbus_obj, "handle_fido_uaf_discover",
1281 G_CALLBACK(_dbus_on_fido_discover), NULL);
1283 g_signal_connect(fido_dbus_obj, "handle_fido_uaf_check_policy",
1284 G_CALLBACK(_dbus_on_fido_uaf_is_supported), NULL);
1286 g_signal_connect(fido_dbus_obj, "handle_fido_uaf_process_operation",
1287 G_CALLBACK(_dbus_on_fido_process_operation), NULL);
1289 // g_signal_connect(fido_dbus_obj, "handle_fido_uaf_notify_result",
1290 // G_CALLBACK(_dbus_on_fido_uaf_notify_result), NULL);
1292 g_signal_connect(fido_dbus_obj, "handle_ui_response",
1293 G_CALLBACK(_auth_ui_selector_on_ui_response), NULL);
1295 if (_asm_plugin_mgr_init() != FIDO_ERROR_NONE) {
1296 _ERR("Falied to init ASM plugin manager");
1297 dlog_print(DLOG_INFO, "FIDO", "_asm_plugin_mgr_init failed");
1305 on_name_acquired (GDBusConnection *connection,
1309 _INFO("on_name_acquired");
1314 on_name_lost (GDBusConnection *connection,
1318 _INFO("on_name_lost");
1319 _asm_plugin_mgr_destroy();
1324 __initialize_dbus(void)
1326 _INFO("__initialize_dbus Enter");
1328 owner_id = g_bus_own_name (G_BUS_TYPE_SYSTEM,
1330 G_BUS_NAME_OWNER_FLAGS_NONE,
1337 _INFO("owner_id=[%d]", owner_id);
1340 _INFO("gdbus own failed!!");
1344 _INFO("g_bus_own_name SUCCESS");
1351 #if !GLIB_CHECK_VERSION(2,35,0)
1355 if (__initialize_dbus() == false) {
1356 _ERR("DBUS Initialization Failed");
1364 GMainLoop *mainloop = NULL;
1366 dlog_print(DLOG_INFO, "FIDO", "start");
1368 _INFO("Starting FIDO SVC");
1370 mainloop = g_main_loop_new(NULL, FALSE);
1374 g_main_loop_run(mainloop);
1376 _INFO("Ending FIDO SVC");