Added DisplayPNGCharacteristicsDescriptor for Registration Assertion
[platform/core/account/fido-client.git] / server / fido_uaf_policy_checker.c
1 /*
2  * Copyright (c) 2014 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 #include <string.h>
19 #include <stdio.h>
20
21 #include "fido_keys.h"
22 #include "fido_logs.h"
23 #include "fido_uaf_policy_checker.h"
24 #include "fido_json_handler.h"
25
26 //static _fido_asm_proxy_t*
27 //__dup_asm_proxy(const _fido_asm_proxy_t *src)
28 //{
29 //    _fido_asm_proxy_t *dest = calloc(1, sizeof(_fido_asm_proxy_t));
30 //    dest->bin_path = strdup(src->bin_path);
31 //    dest->dbus_info = strdup(src->dbus_info);
32 //    dest->dbus_interface_name = strdup(src->dbus_interface_name);
33 //    dest->dbus_method_name = strdup(src->dbus_method_name);
34 //    dest->dbus_obj_path = strdup(src->dbus_obj_path);
35 //    dest->vendor = strdup(src->vendor);
36
37 //    dest->dbus_proxy = src->dbus_proxy;
38
39 //    return dest;
40 //}
41
42 static gint
43 _int_cmp(gconstpointer a, gconstpointer b)
44 {
45     int int1 = GPOINTER_TO_INT(a);
46     int int2 = GPOINTER_TO_INT(b);
47     return (int1 - int2);
48 }
49
50 bool
51 _policy_checker_is_matched(_match_criteria_t *match_criteria, fido_authenticator_s *auth_info)
52 {
53     _INFO("_policy_checker_is_matched");
54
55     /* -1 means the int value is not present, so we should ignore that. */
56
57     /* 1. If any AAID is mentioned in match_criteria, then atleast one AAID should match */
58     GList *aaid_list = match_criteria->aaid_list;
59
60     if (aaid_list &&
61             (g_list_length(aaid_list)) &&
62             (auth_info->aaid) &&
63             (strlen(auth_info->aaid) > 0)) {
64         aaid_list = g_list_first(aaid_list);
65         if (g_list_find_custom(aaid_list, auth_info->aaid, (GCompareFunc)strcmp) == NULL) {
66             _ERR("AAID match failed");
67             return false;
68         }
69     }
70
71
72     /* 2. If any Vendor ID is mentioned in match_criteria, then atleast one Vendor ID should match */
73     GList *vendor_list = match_criteria->vendor_list;
74
75     if (vendor_list && auth_info->aaid) {
76         char *auth_aaid = strdup(auth_info->aaid);
77         char *auth_vendor = strtok(auth_aaid, "#");
78
79         if (vendor_list &&
80                 (g_list_length(vendor_list)) &&
81                 auth_vendor &&
82                 (strlen(auth_vendor) > 0)) {
83             vendor_list = g_list_first(vendor_list);
84             if (g_list_find_custom(vendor_list, auth_vendor, (GCompareFunc)strcmp) == NULL) {
85                 _ERR("Vendor ID match failed");
86
87                 SAFE_DELETE(auth_aaid);
88                 return false;
89             }
90         }
91         SAFE_DELETE(auth_aaid);
92     }
93
94     _INFO("keyid matching");
95
96     /* 3. If any Key ID is mentioned in match_criteria, then atleast one Key ID should match */
97     GList *key_id_list = match_criteria->key_id_list;
98
99     if (key_id_list != NULL) {
100
101         if (auth_info->key_ids == NULL) {
102             _ERR("keyID match failed");
103             return false;
104         }
105
106         GList *auth_key_ids = auth_info->key_ids;
107
108         GList *common_key_id_list = NULL;
109
110         key_id_list = g_list_first(key_id_list);
111         auth_key_ids = g_list_first(auth_key_ids);
112
113         _INFO("match_criteria keyid count = [%d]", g_list_length(key_id_list));
114         _INFO("auth info keyid count = [%d]", g_list_length(auth_key_ids));
115
116         GList *key_id_iter = g_list_first(key_id_list);
117         while (key_id_iter != NULL) {
118             char *key_id = (char*) (key_id_iter->data);
119             if (key_id) {
120                 if (g_list_find_custom(auth_key_ids, key_id, (GCompareFunc)strcmp) != NULL) {
121                     _INFO("keyid matched [%s]", key_id);
122                     common_key_id_list = g_list_append(common_key_id_list, strdup(key_id));
123                 }
124             }
125             key_id_iter = key_id_iter->next;
126         }
127
128         if (common_key_id_list == NULL) {
129             _ERR("keyID match failed");
130             return false;
131         }
132
133         common_key_id_list = g_list_first(common_key_id_list);
134
135         /*Set common keyIds in match*/
136         g_list_free_full(match_criteria->key_id_list, free);
137         match_criteria->key_id_list = common_key_id_list;
138
139         _INFO("keyID matched count [%d]", g_list_length(match_criteria->key_id_list));
140
141     }
142
143     _INFO("User verification matching");
144
145     /* 4. User verification match */
146     if (match_criteria->user_verification != -1) {
147         if ((match_criteria->user_verification == auth_info->user_verification)
148                 ||
149                 (
150                         ((auth_info->user_verification & _USER_VER_METHOD_ALL) == 0)
151                         &&
152                         ((match_criteria->user_verification & _USER_VER_METHOD_ALL) == 0)
153                         &&
154                         ((auth_info->user_verification & match_criteria->user_verification) != 0)
155                 )
156         )
157             _INFO("User verification match passed");
158         else {
159             _ERR("User verification match failed");
160             return false;
161         }
162     }
163
164     /* 5. Key protection field bit matching */
165     if ((match_criteria->key_protection != -1) && auth_info->key_protection) {
166         if (((match_criteria->key_protection) && (auth_info->key_protection)) == 0) {
167             _ERR("Key protection match failed");
168             return false;
169         }
170     }
171
172     /* 6. Matcher Protection field bit matching */
173     if ((match_criteria->matcher_protection != -1) && auth_info->matcher_protection) {
174         if (((match_criteria->matcher_protection) && (auth_info->matcher_protection)) == 0) {
175             _ERR("Matcher protection match failed");
176             return false;
177         }
178     }
179
180     /* 7. Attachment hint field bit matching */
181     if ((match_criteria->attachement_hint != -1) && auth_info->attachment_hint) {
182         if (((match_criteria->attachement_hint) && (auth_info->attachment_hint)) == 0) {
183             _ERR("Attachment hint match failed");
184             return false;
185         }
186     }
187
188     /* 8. TC Display field bit matching */
189     if ((match_criteria->tc_display != -1) && auth_info->tc_display) {
190         if (((match_criteria->tc_display) && (auth_info->tc_display)) == 0) {
191             _ERR("Attachment hint match failed");
192             return false;
193         }
194     }
195
196     /* 9. If any algo is mentioned in match_criteria, then atleast one algo should match */
197     GList *match_algo_list = match_criteria->auth_algo_list;
198     if (match_algo_list && (g_list_length(match_algo_list))
199             && (auth_info->authentication_algorithm)) {
200         match_algo_list = g_list_first(match_algo_list);
201         if (g_list_find_custom(match_algo_list, GINT_TO_POINTER(auth_info->authentication_algorithm), (GCompareFunc)_int_cmp) == NULL) {
202             _ERR("Algorithm match failed");
203             return false;
204         }
205     }
206
207     /* 10. If any assertion scheme is mentioned in match_criteria, then atleast one assertion scheme should match */
208     GList *assertion_list = match_criteria->assertion_scheme_list;
209     if (assertion_list && (g_list_length(assertion_list))
210             && (auth_info->assertion_scheme) && (strlen(auth_info->assertion_scheme) > 0)) {
211         assertion_list = g_list_first(assertion_list);
212         if (g_list_find_custom(assertion_list, auth_info->assertion_scheme, (GCompareFunc)strcmp) == NULL)
213         {
214             _ERR("Assertion scheme match failed");
215             return false;
216         }
217     }
218
219     /* 11. If any attestation type is mentioned in match_criteria, then atleast one attestation type should match */
220     GList *attestation_type_list = match_criteria->attestation_type_list;
221     if (attestation_type_list && (g_list_length(attestation_type_list))
222             && (auth_info->attestation_types)) {
223         attestation_type_list = g_list_first(attestation_type_list);
224         if (g_list_find_custom(attestation_type_list, GINT_TO_POINTER(auth_info->attestation_types), (GCompareFunc)_int_cmp) == NULL) {
225             _ERR("Attestation type match failed");
226             return false;
227         }
228     }
229
230     /* TODO : 12. Auth version */
231
232     /* TODO : 13. Extension */
233
234     _INFO("_policy_checker_is_matched true");
235
236     return true;
237 }
238
239 int
240 _get_attestation_type(_match_criteria_t *match_criteria, fido_authenticator_s *auth_info)
241 {
242      _INFO("_get_attestation_type");
243
244     if (match_criteria && match_criteria->attestation_type_list) {
245
246         GList *match_att_list_iter = g_list_first(match_criteria->attestation_type_list);
247         while (match_att_list_iter != NULL) {
248
249             int match_att_type = GPOINTER_TO_INT(match_att_list_iter->data);
250
251             if (auth_info && auth_info->attestation_types) {
252
253                 GList *auth_att_list_iter = g_list_first(auth_info->attestation_types);
254                 while (auth_att_list_iter != NULL) {
255
256                     int auth_att_type = GPOINTER_TO_INT(auth_att_list_iter->data);
257
258                     if (match_att_type == auth_att_type) {
259                         _INFO("_get_attestation_type end [%d]", match_att_type);
260                         return match_att_type;
261                     }
262                 }
263             }
264             match_att_list_iter = match_att_list_iter->data;
265         }
266     }
267     else {
268         if (auth_info->attestation_types != NULL) {
269             GList *att_type_iter = g_list_first(auth_info->attestation_types);
270
271             /*Returning first attestation type in case policy does not mandate any*/
272             while (att_type_iter != NULL) {
273                 int auth_att_type = GPOINTER_TO_INT(att_type_iter->data);
274                 _INFO("Returning first attestation type in case policy does not mandate any [%d]", auth_att_type);
275                 return auth_att_type;
276             }
277         }
278     }
279
280     _ERR("_get_attestation_type end");
281     return -1;
282 }
283
284 static char *
285 __get_verification_method_string(unsigned long int ver_method)
286 {
287     char *ver_str = calloc(1, 128);
288
289     switch (ver_method) {
290
291     case _USER_VER_METHOD_PRESENCE:
292         snprintf(ver_str, 127, "%s", "Presence Authenticator");
293         break;
294
295     case _USER_VER_METHOD_FINGERPRINT:
296         snprintf(ver_str, 127, "%s", "Fingerprint Authenticator");
297         break;
298
299     case _USER_VER_METHOD_PASSCODE:
300         snprintf(ver_str, 127, "%s", "Passcode Authenticator");
301         break;
302
303     case _USER_VER_METHOD_VOICE_PRINT:
304         snprintf(ver_str, 127, "%s", "Voice Print Authenticator");
305         break;
306
307     case _USER_VER_METHOD_FACE_PRINT:
308         snprintf(ver_str, 127, "%s", "Face Print Authenticator");
309         break;
310
311     case _USER_VER_METHOD_LOCATION:
312         snprintf(ver_str, 127, "%s", "Location Authenticator");
313         break;
314
315     case _USER_VER_METHOD_EYE_PRINT:
316         snprintf(ver_str, 127, "%s", "Eye Print Authenticator");
317         break;
318
319     case _USER_VER_METHOD_PATTERN:
320         snprintf(ver_str, 127, "%s", "Pattern Authenticator");
321         break;
322
323     case _USER_VER_METHOD_HAND_PRINT:
324         snprintf(ver_str, 127, "%s", "Hand Print Authenticator");
325         break;
326
327 //    case _USER_VER_METHOD_NONE:
328 //        snprintf(ver_str, "%s", "");
329 //        break;
330
331     case _USER_VER_METHOD_ALL:
332         snprintf(ver_str, 127, "%s", "All Authenticator");
333         break;
334
335     default:
336         snprintf(ver_str, 127, "%s", "Other Type");
337         break;
338     }
339
340     return ver_str;
341 }
342
343 static GList*
344 __copy_string_list(GList *src)
345 {
346     RET_IF_FAIL(src != NULL, NULL);
347
348     GList *dest = NULL;
349
350     GList *iter = g_list_first(src);
351     while (iter != NULL) {
352         char *str = (char*)(iter->data);
353         dest = g_list_append(dest, strdup(str));
354
355         iter = iter->next;
356     }
357
358     return dest;
359 }
360
361 static GList*
362 __copy_png_list(GList *src_list)
363 {
364         RET_IF_FAIL(src_list != NULL, NULL);
365
366         GList *dest = NULL;
367
368         /*fido_display_png_characteristics_descriptor_s list*/
369         GList *iter = g_list_first(src_list);
370
371         while (iter != NULL) {
372                 fido_display_png_characteristics_descriptor_s *src_data =
373                                 (fido_display_png_characteristics_descriptor_s *)(iter->data);
374
375                 if (src_data != NULL) {
376                         fido_display_png_characteristics_descriptor_s *dest_data =
377                                         calloc(1, sizeof(fido_display_png_characteristics_descriptor_s));
378
379                         dest_data->bit_depth = src_data->bit_depth;
380                         dest_data->color_type = src_data->color_type;
381                         dest_data->compression = src_data->compression;
382                         dest_data->filter = src_data->filter;
383                         dest_data->height = src_data->height;
384                         dest_data->interlace = src_data->interlace;
385                         dest_data->width = src_data->width;
386                         /*TODO: dest_data->plte clone*/
387                         if (src_data->plte != NULL) {
388                                 GList *p_iter = g_list_first(src_data->plte);
389                                 while (p_iter != NULL) {
390
391                                         fido_rgb_pallette_entry_s *plte_src_data = (fido_rgb_pallette_entry_s*)(p_iter->data);
392                                         if (plte_src_data != NULL) {
393                                                 fido_rgb_pallette_entry_s *plte_dest_data = calloc(1, sizeof(fido_rgb_pallette_entry_s));
394                                                 plte_dest_data->r = plte_src_data->r;
395                                                 plte_dest_data->g = plte_src_data->g;
396                                                 plte_dest_data->b = plte_src_data->b;
397
398                                                 dest_data->plte = g_list_append(dest_data->plte, plte_dest_data);
399                                         }
400                                         p_iter = p_iter->next;
401                                 }
402                         }
403
404                         if (dest_data->plte != NULL)
405                                 dest_data->plte = g_list_first(dest_data->plte);
406
407                         dest_data->plte =
408                         dest = g_list_append(dest, dest_data);
409                 }
410
411                 iter = iter->next;
412         }
413
414         if (dest != NULL)
415                 dest = g_list_first(dest);
416
417         return dest;
418 }
419
420 /* Returns _matched_auth_data_t list*/
421 GList *
422 _policy_checker_get_matched_auth_list(_policy_t *policy, GList *auth_list)
423 {
424     _INFO("_policy_checker_get_matched_auth_list");
425
426     if (policy == NULL)
427         _INFO("policy is NULL");
428
429     if (auth_list == NULL)
430         _INFO("auth_list is NULL");
431
432     RET_IF_FAIL(policy != NULL, NULL);
433     RET_IF_FAIL(auth_list != NULL, NULL);
434
435     //    _match_criteria_t *match_criteria_or = NULL;
436     GList *allowed_list = NULL;
437     GList *disallowed_list = policy->disallowed_list;
438     GList *accepted_list = policy->accepted_list;
439
440     if (accepted_list != NULL)
441         _INFO("accepted_list count = [%d]", g_list_length(accepted_list));
442
443     if (disallowed_list != NULL)
444         _INFO("allowed_list count = [%d]", g_list_length(disallowed_list));
445
446     GList *accepted_list_iter = g_list_first(accepted_list);
447     while (accepted_list_iter != NULL) {
448
449         GList *accepted_list_internal = (GList *) accepted_list_iter->data;
450         GList *accepted_list_internal_iter = g_list_first(accepted_list_internal);
451         while (accepted_list_internal_iter != NULL) {
452             _match_criteria_t *match_info = (_match_criteria_t *) accepted_list_internal_iter->data;
453
454             GList *auth_list_iter = g_list_first(auth_list);
455             while (auth_list_iter != NULL) {
456                 fido_authenticator_s *authenticator = (fido_authenticator_s*) (auth_list_iter->data);
457
458                 if (_policy_checker_is_matched(match_info, authenticator)) {
459                     _INFO("[%s] is matched from allowed list", authenticator->aaid);
460
461                     /*Disallowed list can be NULL, which means put all which are matching with accepted list*/
462
463                     if (disallowed_list != NULL) {
464
465                         GList *disallowed_list_iter = g_list_first(disallowed_list);
466                         while (disallowed_list_iter != NULL) {
467                             _match_criteria_t *disallowed_match_info = (_match_criteria_t *) disallowed_list_iter->data;
468
469                             if (!_policy_checker_is_matched(disallowed_match_info, authenticator)) {
470                                 _INFO("[%s] is not in disallowed list", authenticator->aaid);
471                                 _matched_auth_data_t *matched_auth_data = (_matched_auth_data_t*) calloc(1, sizeof(_matched_auth_data_t));
472                                 RET_IF_FAIL(matched_auth_data, NULL);
473
474                                 /*TODO : ASM must send auth index*/
475                                 if (authenticator->auth_index != NULL)
476                                     matched_auth_data->auth_index = strdup(authenticator->auth_index);
477                                 else
478                                     _ERR("auth index missing");
479
480                                 matched_auth_data->att_type = _get_attestation_type(match_info, authenticator);
481
482                                 if (authenticator->title != NULL)
483                                     matched_auth_data->label = strdup(authenticator->title);
484                                 else {
485                                     _ERR("title missing, putting ver method");
486                                     /*If label is null, set verification method name instead*/
487                                     matched_auth_data->label = __get_verification_method_string(authenticator->user_verification);
488                                 }
489
490
491                                 if (authenticator->asm_id != NULL)
492                                     matched_auth_data->asm_id = strdup(authenticator->asm_id);
493                                 else
494                                     _ERR("Authenticator does not have any ASM ID!!");
495
496                                 matched_auth_data->key_ids = __copy_string_list(match_info->key_id_list);
497                                                                 /*fido_display_png_characteristics_descriptor_s list*/
498                                                                 matched_auth_data->tc_display_png_characteristics =
499                                                                                 __copy_png_list(authenticator->tc_display_png_characteristics);
500
501                                 allowed_list = g_list_append(allowed_list, matched_auth_data);
502                             }
503                             disallowed_list_iter = disallowed_list_iter->next;
504                         }
505                     }
506                     else {
507                         _INFO("[%s] adding since no disallowed list", authenticator->aaid);
508                         _matched_auth_data_t *matched_auth_data = (_matched_auth_data_t*) calloc(1, sizeof(_matched_auth_data_t));
509                         RET_IF_FAIL(matched_auth_data, NULL);
510
511                         matched_auth_data->auth_index = strdup(authenticator->auth_index);
512                         matched_auth_data->att_type = _get_attestation_type(match_info, authenticator);
513                         if (authenticator->title != NULL)
514                             matched_auth_data->label = strdup(authenticator->title);
515                         else {
516                             _ERR("title missing, putting ver method");
517                             /*If label is null, set verification method name instead*/
518                             matched_auth_data->label = __get_verification_method_string(authenticator->user_verification);
519                         }
520
521                         if (authenticator->asm_id != NULL)
522                             matched_auth_data->asm_id = strdup(authenticator->asm_id);
523                         else
524                             _ERR("Authenticator does not have any ASM ID!!");
525
526                         matched_auth_data->key_ids = __copy_string_list(match_info->key_id_list);
527
528                         allowed_list = g_list_append(allowed_list, matched_auth_data);
529                     }
530                 }
531                 auth_list_iter = auth_list_iter->next;
532             }
533             accepted_list_internal_iter = accepted_list_internal_iter->next;
534         }
535         accepted_list_iter = accepted_list_iter->next;
536     }
537
538     if (allowed_list != NULL)
539         allowed_list = g_list_first(allowed_list);
540
541     return allowed_list;
542 }
543
544 /* Returns _matched_auth_dereg_t list */
545 GList*
546 _policy_checker_get_matched_auth_list_dereg(const char *app_id, GList *input_auth_list, GList *available_auth_list)
547 {
548         _INFO("");
549
550         RET_IF_FAIL(app_id, NULL);
551     RET_IF_FAIL(input_auth_list, NULL);
552     RET_IF_FAIL(available_auth_list, NULL);
553
554         _INFO("");
555
556     GList *matched_auth_dereg_list = NULL;
557
558     GList *input_auth_list_iter = g_list_first(input_auth_list);
559     while (input_auth_list_iter != NULL) {
560         _dereg_auth_info_t *dereg_auth_info = (_dereg_auth_info_t*) (input_auth_list_iter->data);
561
562         GList *available_auth_list_iter = g_list_first(available_auth_list);
563         while (available_auth_list_iter != NULL) {
564             fido_authenticator_s *authenticator = (fido_authenticator_s*) (available_auth_list_iter->data);
565
566                         if (dereg_auth_info->aaid != NULL)
567                                 _INFO("Input AAID = [%s]", dereg_auth_info->aaid);
568
569                         if (authenticator->aaid != NULL)
570                                 _INFO("Authenticator AAID = [%s]", authenticator->aaid);
571                         
572             if (dereg_auth_info->aaid && authenticator->aaid && !strcmp(dereg_auth_info->aaid, authenticator->aaid)) {
573                 _matched_auth_dereg_t *matched_auth_dereg = (_matched_auth_dereg_t*) calloc(1, sizeof(_matched_auth_dereg_t));
574                 RET_IF_FAIL(matched_auth_dereg, NULL);
575
576                 matched_auth_dereg->auth_index = strdup(authenticator->auth_index);
577                 matched_auth_dereg->app_id = strdup(app_id);
578                 matched_auth_dereg->key_id = strdup(dereg_auth_info->key_id);
579                 if (authenticator->asm_id != NULL)
580                     matched_auth_dereg->asm_id = strdup(authenticator->asm_id);
581                 else
582                     _ERR("Authenticator does not have any ASM ID!!");
583
584                                 _INFO("");
585                 matched_auth_dereg_list = g_list_append(matched_auth_dereg_list, matched_auth_dereg);
586             }
587             available_auth_list_iter = available_auth_list_iter->next;
588         }
589         input_auth_list_iter = input_auth_list_iter->next;
590     }
591
592     return matched_auth_dereg_list;
593 }