1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*******************************************************************************
3  * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
4  * All rights reserved.
5  *******************************************************************************/
6 
7 #ifdef HAVE_CONFIG_H
8 #include <config.h>
9 #endif
10 
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdarg.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <unistd.h>
19 #include <ctype.h>
20 #include <dirent.h>
21 #include <curl/curl.h>
22 
23 #include "tss2_mu.h"
24 #include "fapi_util.h"
25 #include "fapi_policy.h"
26 #include "fapi_crypto.h"
27 #include "ifapi_helpers.h"
28 #include "ifapi_json_serialize.h"
29 #include "ifapi_json_deserialize.h"
30 #include "tpm_json_deserialize.h"
31 #define LOGMODULE fapi
32 #include "util/log.h"
33 #include "util/aux_util.h"
34 
35 /** Create template for key creation based on type flags.
36  *
37  * Based on passed flags the TPM2B_PUBLIC data which is used for key
38  * creation will be adapted.
39  *
40  * @param[in] type The flags describing the key type.
41  * @param[in] policy The flag whether a policy is used.
42  * @param[out] template The template including the TPM2B_PUBLIC which will
43  *             be used for key creation.
44  * @retval TSS2_RC_SUCCESS if the template can be generated.
45  * @retval TSS2_FAPI_RC_BAD_VALUE If an invalid combination of flags was used.
46  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
47  */
48 TSS2_RC
ifapi_set_key_flags(const char * type,bool policy,IFAPI_KEY_TEMPLATE * template)49 ifapi_set_key_flags(const char *type, bool policy, IFAPI_KEY_TEMPLATE *template)
50 {
51     TSS2_RC r = TSS2_RC_SUCCESS;
52     char *type_dup = NULL;
53     TPMA_OBJECT attributes = 0;
54     UINT32 handle;
55     int pos;
56     bool exportable = false;
57 
58     memset(template, 0, sizeof(IFAPI_KEY_TEMPLATE));
59     type_dup = strdup(type);
60     return_if_null(type_dup, "Out of memory.", TSS2_FAPI_RC_MEMORY);
61 
62     char *flag = strtok(type_dup, ", ");
63 
64     /* The default store will be the user directory */
65     template->system = TPM2_NO;
66 
67     /* Loop over all comma or space separated flags */
68     while (flag != NULL) {
69         if (strcasecmp(flag, "system") == 0) {
70             template->system = TPM2_YES;
71         } else if (strcasecmp(flag, "sign") == 0) {
72             attributes |= TPMA_OBJECT_SIGN_ENCRYPT;
73         } else if (strcasecmp(flag, "decrypt") == 0) {
74             attributes |= TPMA_OBJECT_DECRYPT;
75         } else if (strcasecmp(flag, "restricted") == 0) {
76             attributes |= TPMA_OBJECT_RESTRICTED;
77         } else if (strcasecmp(flag, "exportable") == 0) {
78             /* TPMA_OBJECT_ENCRYPTEDDUPLICATION will not be set because no inner
79                symmetric encryption will be used */
80             exportable = true;
81         } else if (strcasecmp(flag, "noda") == 0) {
82             attributes |= TPMA_OBJECT_NODA;
83         } else if (strncmp(flag, "0x", 2) == 0) {
84             sscanf(&flag[2], "%"SCNx32 "%n", &handle, &pos);
85             if ((size_t)pos != strlen(flag) - 2) {
86                 goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Invalid flag: %s",
87                            error, flag);
88             }
89             template->persistent_handle = handle;
90             template->persistent = TPM2_YES;
91         } else {
92             goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Invalid flag: %s",
93                        error, flag);
94         }
95         flag = strtok(NULL, " ,");
96     }
97     if (exportable) {
98         /* Clear flags preventing duplication */
99         attributes &= ~TPMA_OBJECT_FIXEDTPM;
100         attributes &= ~TPMA_OBJECT_FIXEDPARENT;
101     } else {
102         attributes |= TPMA_OBJECT_FIXEDTPM;
103         attributes |= TPMA_OBJECT_FIXEDPARENT;
104     }
105     /* Set default flags */
106     attributes |= TPMA_OBJECT_SENSITIVEDATAORIGIN;
107     if (!policy)
108         attributes |= TPMA_OBJECT_USERWITHAUTH;
109     else
110         attributes |= TPMA_OBJECT_ADMINWITHPOLICY;
111 
112     /* Check whether flags are appropriate */
113     if (attributes & TPMA_OBJECT_RESTRICTED &&
114             attributes & TPMA_OBJECT_SIGN_ENCRYPT &&
115             attributes & TPMA_OBJECT_DECRYPT) {
116         goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
117                    "Exactly either sign or decrypt must be set.",
118                    error);
119     }
120 
121     template->public.publicArea.objectAttributes = attributes;
122     SAFE_FREE(type_dup);
123     return TSS2_RC_SUCCESS;
124 
125 error:
126     SAFE_FREE(type_dup);
127     return r;
128 }
129 
130 /** Create template for nv object  creation based on type flags.
131  *
132  * Based on passed flags the TPM2B_NV_PUBLIC data which is used for key
133  * creation will be adapted.
134  * @param[in] type The flags describing the nv object type.
135  * @param[in] policy The flag whether a policy is used.
136  * @param[out] template The template including the TPM2B_NV_PUBLIC which will
137  *             be used for nv object creation.
138  * @retval TSS2_RC_SUCCESS if the template can be generated.
139  * @retval TSS2_FAPI_RC_BAD_VALUE If an invalid combination of flags was used.
140  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
141  */
142 TSS2_RC
ifapi_set_nv_flags(const char * type,IFAPI_NV_TEMPLATE * template,const char * policy)143 ifapi_set_nv_flags(const char *type, IFAPI_NV_TEMPLATE *template,
144                    const char *policy)
145 {
146     TSS2_RC r = TSS2_RC_SUCCESS;
147     char *type_dup = NULL;
148     TPMA_NV attributes = 0;
149     UINT32 handle;
150     int pos;
151     UINT32 size = 0;
152     size_t type_count = 0;
153 
154     memset(template, 0, sizeof(IFAPI_NV_TEMPLATE));
155     type_dup = strdup(type);
156     return_if_null(type_dup, "Out of memory.", TSS2_FAPI_RC_MEMORY);
157     /* The default store will be the user directory */
158     template->system = TPM2_NO;
159 
160     char *flag = strtok(type_dup, ", ");
161 
162     /* Loop over all comma or space separated flags */
163     while (flag != NULL) {
164         if (strcasecmp(flag, "system") == 0) {
165             template->system = TPM2_YES;
166         } else if (strcasecmp(flag, "bitfield") == 0) {
167             attributes |= TPM2_NT_BITS << TPMA_NV_TPM2_NT_SHIFT;
168             type_count += 1;
169         } else if (strcasecmp(flag, "counter") == 0) {
170             attributes |= TPM2_NT_COUNTER << TPMA_NV_TPM2_NT_SHIFT;
171             type_count += 1;
172         } else if (strcasecmp(flag, "pcr") == 0) {
173             attributes |= TPM2_NT_EXTEND << TPMA_NV_TPM2_NT_SHIFT;
174             type_count += 1;
175         } else if (strcasecmp(flag, "noda") == 0) {
176             attributes |= TPMA_NV_NO_DA;
177         } else if (strncmp(flag, "0x", 2) == 0) {
178             sscanf(&flag[2], "%"SCNx32 "%n", &handle, &pos);
179             if ((size_t)pos != strlen(flag) - 2) {
180                 goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Invalid flag: %s",
181                            error, flag);
182             }
183             template->public.nvIndex = handle;
184         } else {
185             goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Invalid flag: %s",
186                        error, flag);
187         }
188         flag = strtok(NULL, " ,");
189     }
190     if (type_count > 1) {
191         goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
192                    "Only one type of NV object can be set.", error);
193     }
194     if (type_count == 0) {
195         /* Normal NV space will be defined */
196         attributes |= TPM2_NT_ORDINARY << TPMA_NV_TPM2_NT_SHIFT;
197         if (size == 0)
198             size = 64;
199     }
200     /* If type extend is used the size will be set during the merging of the crypto
201        profile depending on the nameHashAlg stored in the profile.
202        The size of counter and bitfield will be determined by the TPM. */
203 
204     if (policy && strlen(policy) > 0) {
205         attributes |= TPMA_NV_POLICYWRITE;
206         attributes |= TPMA_NV_POLICYREAD;
207     } else {
208         attributes |= TPMA_NV_AUTHREAD;
209         attributes |= TPMA_NV_AUTHWRITE;
210     }
211 
212     attributes |= TPMA_NV_READ_STCLEAR;
213     attributes |= TPMA_NV_WRITE_STCLEAR;
214     template->public.attributes = attributes;
215     template->hierarchy = TPM2_RH_OWNER;
216     template->public.dataSize = size;
217 
218     SAFE_FREE(type_dup);
219     return TSS2_RC_SUCCESS;
220 
221 error:
222     SAFE_FREE(type_dup);
223     return r;
224 }
225 
226 /**  Determine whether path is of certain type.
227  *
228  * @param[in] path The path to be checked.
229  * @param[in] type sub-string at the beginning of the path to be checked.
230  *
231  * @retval true if the path name starts with type.
232  * @retval false if not.
233  */
234 bool
ifapi_path_type_p(const char * path,const char * type)235 ifapi_path_type_p(const char *path, const char *type)
236 {
237     size_t pos = 0;
238     char *end;
239     int end_pos;
240 
241     if (strncmp("/", path, 1) == 0)
242         pos = 1;
243     if (strcmp(&path[pos], type) == 0)
244         return true;
245 
246     end = strchr(&path[pos], IFAPI_FILE_DELIM_CHAR);
247     if (!end)
248         /* No meaningful path */
249         return false;
250     end_pos = (int)(end - path);
251 
252     /* Check sub-string and following delimiter. */
253     if (strlen(path) - pos > 3 &&
254             strncasecmp(type, &path[pos], strlen(type)) == 0 && end &&
255             strncmp(IFAPI_FILE_DELIM, &path[end_pos], 1) == 0)
256         return true;
257     return false;
258 }
259 
260 /** Get ESYS handle for a hierarchy path.
261  *
262  * @param[in] path The path to be checked.
263  *
264  * @retval The ESAPI handle for the hierarchy defined in path.
265  * @retval 0 if not handle can be assigned.
266  */
267 ESYS_TR
ifapi_get_hierary_handle(const char * path)268 ifapi_get_hierary_handle(const char *path)
269 {
270     int pos = 0;
271 
272     if (strncmp("/", path, 1) == 0)
273         pos = 1;
274     if (strcmp(&path[pos], "HE") == 0) {
275         return ESYS_TR_RH_ENDORSEMENT;
276     }
277     if (strcmp(&path[pos], "HS") == 0) {
278         return ESYS_TR_RH_OWNER;
279     }
280     if (strcmp(&path[pos], "LOCKOUT") == 0) {
281         return ESYS_TR_RH_LOCKOUT;
282     }
283     return 0;
284 }
285 
286 /** Determine whether path describes a hierarchy object.
287  *
288  * It will be checked whether the path describes a hierarch. A key path
289  * with a hierarchy will not deliver true.
290  *
291  * @param[in] path The path to be checked.
292  *
293  * @retval true if the path describes a hierarchy.
294  * @retval false if not.
295  */
296 bool
ifapi_hierarchy_path_p(const char * path)297 ifapi_hierarchy_path_p(const char *path)
298 {
299     size_t pos1 = 0;
300     size_t pos2 = 0;
301     char *start;
302 
303     if (strncmp("/", path, 1) == 0)
304         pos1 = 1;
305     /* Skip profile if it does exist in path */
306     if (strncmp("P_", &path[pos1], 2) == 0) {
307         start = strchr(&path[pos1], IFAPI_FILE_DELIM_CHAR);
308         if (start) {
309             pos2 = (int)(start - &path[pos1]);
310             if (strncmp("/", &path[pos2], 1) == 0)
311                 pos2 += 1;
312             if (strncmp("/", &path[pos2], 1) == 0)
313                 pos2 += 1;
314         }
315     }
316     /* Check whether only hierarchy is specified in path */
317     if ((strncasecmp(&path[pos1 + pos2], "HS", 2) == 0 ||
318          strncasecmp(&path[pos1 + pos2], "HE", 2) == 0 ||
319          strncasecmp(&path[pos1 + pos2], "HE", 2) == 0 ||
320          strncasecmp(&path[pos1 + pos2], "HP", 2) == 0 ||
321          strncasecmp(&path[pos1 + pos2], "HN", 2) == 0 ||
322          strncasecmp(&path[pos1 + pos2], "HP", 2) == 0)
323         && (strlen(path) == pos1 + pos2 + 2 ||
324             (strlen(path) == pos1 + pos2 + 3 &&
325              path[pos1 + pos2 + 2] == IFAPI_FILE_DELIM_CHAR))){
326         return true;
327     } else if (strncasecmp(&path[pos1 + pos2], "LOCKOUT", 7) == 0
328                && (strlen(path) == pos1 + pos2 + 7 ||
329                    (strlen(path) == pos1 + pos2 + 8 &&
330                     path[pos1 + pos2 + 7] == IFAPI_FILE_DELIM_CHAR))) {
331         return true;
332     }
333     return false;
334 }
335 
336 /** Compare two variables of type TPM2B_ECC_PARAMETER.
337  *
338  * @param[in] in1 variable to be compared with in2.
339  * @param[in] in2 variable to be compared with in1.
340  *
341  * @retval true if the variables are equal.
342  * @retval false if not.
343  */
344 bool
ifapi_TPM2B_ECC_PARAMETER_cmp(TPM2B_ECC_PARAMETER * in1,TPM2B_ECC_PARAMETER * in2)345 ifapi_TPM2B_ECC_PARAMETER_cmp(TPM2B_ECC_PARAMETER *in1,
346                               TPM2B_ECC_PARAMETER *in2)
347 {
348 
349     if (in1->size != in2->size)
350         return false;
351 
352     return memcmp(&in1->buffer[0], &in2->buffer[0], in1->size) == 0;
353 }
354 
355 /** Compare two variables of type TPMS_ECC_POINT.
356  *
357  * @param[in] in1 variable to be compared with in2.
358  * @param[in] in2 variable to be compared with in1.
359  *
360  * @retval true if the variables are equal.
361  * @retval false if not.
362  */
363 bool
ifapi_TPMS_ECC_POINT_cmp(TPMS_ECC_POINT * in1,TPMS_ECC_POINT * in2)364 ifapi_TPMS_ECC_POINT_cmp(TPMS_ECC_POINT *in1, TPMS_ECC_POINT *in2)
365 {
366     LOG_TRACE("call");
367 
368     if (!ifapi_TPM2B_ECC_PARAMETER_cmp(&in1->x, &in2->x))
369         return false;
370 
371     if (!ifapi_TPM2B_ECC_PARAMETER_cmp(&in1->y, &in2->y))
372         return false;
373 
374     return true;
375 }
376 
377 /**  Compare two variables of type TPM2B_DIGEST.
378  *
379  * @param[in] in1 variable to be compared with in2.
380  * @param[in] in2 variable to be compared with in1.
381  *
382  * @retval true if the variables are equal.
383  * @retval false if not.
384  */
385 bool
ifapi_TPM2B_DIGEST_cmp(TPM2B_DIGEST * in1,TPM2B_DIGEST * in2)386 ifapi_TPM2B_DIGEST_cmp(TPM2B_DIGEST *in1, TPM2B_DIGEST *in2)
387 {
388 
389     if (in1->size != in2->size)
390         return false;
391 
392     return memcmp(&in1->buffer[0], &in2->buffer[0], in1->size) == 0;
393 }
394 
395 /** Compare two variables of type TPM2B_PUBLIC_KEY_RSA.
396  *
397  * @param[in] in1 variable to be compared with in2
398  * @param[in] in2 variable to be compared with in1
399  *
400  * @retval true if the variables are equal.
401  * @retval false if not.
402  */
403 bool
ifapi_TPM2B_PUBLIC_KEY_RSA_cmp(TPM2B_PUBLIC_KEY_RSA * in1,TPM2B_PUBLIC_KEY_RSA * in2)404 ifapi_TPM2B_PUBLIC_KEY_RSA_cmp(TPM2B_PUBLIC_KEY_RSA *in1,
405                                TPM2B_PUBLIC_KEY_RSA *in2)
406 {
407 
408     if (in1->size != in2->size)
409         return false;
410 
411     return memcmp(&in1->buffer[0], &in2->buffer[0], in1->size) == 0;
412 }
413 
414 /**  Compare two variables of type TPMU_PUBLIC_ID.
415  *
416  * @param[in] in1 variable to be compared with in2.
417  * @param[in] selector1 key type of first key.
418  * @param[in] in2 variable to be compared with in1.
419  * @param[in] selector2 key type of second key.
420  *
421  * @result true if variables are equal.
422  * @result false if not.
423  */
424 bool
ifapi_TPMU_PUBLIC_ID_cmp(TPMU_PUBLIC_ID * in1,UINT32 selector1,TPMU_PUBLIC_ID * in2,UINT32 selector2)425 ifapi_TPMU_PUBLIC_ID_cmp(TPMU_PUBLIC_ID *in1, UINT32 selector1,
426                          TPMU_PUBLIC_ID *in2, UINT32 selector2)
427 {
428 
429     if (selector1 != selector2)
430         return false;
431 
432     switch (selector1) {
433     case TPM2_ALG_KEYEDHASH:
434         if (!ifapi_TPM2B_DIGEST_cmp(&in1->keyedHash, &in2->keyedHash))
435             return false;
436         break;
437     case TPM2_ALG_SYMCIPHER:
438         if (!ifapi_TPM2B_DIGEST_cmp(&in1->sym, &in2->sym))
439             return false;
440         break;
441     case TPM2_ALG_RSA:
442         if (!ifapi_TPM2B_PUBLIC_KEY_RSA_cmp(&in1->rsa, &in2->rsa))
443             return false;
444         break;
445     case TPM2_ALG_ECC:
446         if (!ifapi_TPMS_ECC_POINT_cmp(&in1->ecc, &in2->ecc))
447             return false;
448         break;
449     default:
450         return false;
451     };
452     return true;
453 }
454 
455 /**
456  * Compare the PUBLIC_ID stored in two  TPMT_PUBLIC structures.
457  * @param[in] in1 the public data with the unique data to be compared with:
458  * @param[in] in2
459  *
460  * @retval true if the variables are equal.
461  * @retval false if not.
462  */
463 bool
ifapi_TPMT_PUBLIC_cmp(TPMT_PUBLIC * in1,TPMT_PUBLIC * in2)464 ifapi_TPMT_PUBLIC_cmp(TPMT_PUBLIC *in1, TPMT_PUBLIC *in2)
465 {
466 
467     if (!ifapi_TPMU_PUBLIC_ID_cmp(&in1->unique, in1->type, &in2->unique, in2->type))
468         return false;
469 
470     return true;
471 }
472 
473 /** Print to allocated string.
474  *
475  * A list of parameters will be printed to an allocated string according to the
476  * format description in the first parameter.
477  *
478  * @param[out] str The allocated output string.
479  * @param[in] fmt The format string (printf formats can be used.)
480  * @param[in] args The list of objects to be printed.
481  *
482  * @retval int The size of the string ff the printing was successful.
483  * @retval -1 if not enough memory can be allocated.
484  */
485 int
vasprintf(char ** str,const char * fmt,va_list args)486 vasprintf(char **str, const char *fmt, va_list args)
487 {
488     int size = 0;
489     va_list tmpa;
490     char *dmy = NULL;
491     va_copy(tmpa, args);
492     size = vsnprintf(dmy, size, fmt, tmpa);
493     va_end(tmpa);
494     if (size < 0) {
495         return -1;
496     }
497     *str = (char *) malloc(size + 1);
498     if (NULL == *str) {
499         return -1;
500     }
501     size = vsprintf(*str, fmt, args);
502     return size;
503 }
504 
505 /** Print to allocated string.
506  *
507  * A list of parameters will be printed to an allocated string according to the
508  * format description in the first parameter.
509  *
510  * @param[out] str The allocated output string.
511  * @param[in] fmt The format string (printf formats can be used.)
512  * @param[in] ... The list of objects to be printed.
513  *
514  * @retval TSS2_RC_SUCCESS If the printing was successful.
515  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
516  */
517 TSS2_RC
ifapi_asprintf(char ** str,const char * fmt,...)518 ifapi_asprintf(char **str, const char *fmt, ...)
519 {
520     int size = 0;
521     va_list args;
522     va_start(args, fmt);
523     size = vasprintf(str, fmt, args);
524     va_end(args);
525     if (size == -1)
526         return TSS2_FAPI_RC_MEMORY;
527     return TSS2_RC_SUCCESS;
528 }
529 
530 /** Divides str into substrings based on a delimiter.
531  *
532  * @param[in] string the string to split.
533  * @param[in] delimiter the delimiter.
534  *
535  * @retval The linked list of substrings.
536  * @retval NULL if the list cannot be created.
537  */
538 NODE_STR_T *
split_string(const char * string,char * delimiter)539 split_string(const char *string, char *delimiter)
540 {
541     NODE_STR_T *node = NULL;
542     NODE_STR_T *start_node = NULL;
543     char *strtok_save = NULL;
544     char *stringdup = NULL;
545     char *substr = NULL;
546     if (string == NULL)
547         return NULL;
548 
549     stringdup = strdup(string);
550     if (stringdup == NULL) {
551         LOG_ERROR("%s", "Out of memory.");
552         goto error_cleanup;
553     }
554     char *stringdup_tokenized = strtok_r(stringdup, delimiter, &strtok_save);
555     if (stringdup_tokenized != NULL) {
556         substr = strdup(stringdup_tokenized);
557     } else {
558         substr = strdup(stringdup);
559     }
560     if (substr == NULL) {
561         LOG_ERROR("%s", "Out of memory.");
562         goto error_cleanup;
563     }
564     do {
565         if (node == NULL) {
566             node = malloc(sizeof(NODE_STR_T));
567             if (node == NULL) {
568                 LOG_ERROR("%s", "Out of memory.");
569                 goto error_cleanup;
570             }
571             node->next = NULL;
572             node->free_string = true;
573             start_node = node;
574         } else {
575             node->next = malloc(sizeof(NODE_STR_T));
576             if (node->next == NULL) {
577                 LOG_ERROR("%s", "Out of memory.");
578                 goto error_cleanup;
579             }
580             node = node->next;
581             node->next = NULL;
582             node->free_string = true;
583         }
584         node->str = substr;
585         substr = strtok_r(NULL, delimiter, &strtok_save);
586         if (substr) {
587             substr = strdup(substr);
588             if (substr == NULL) {
589                 LOG_ERROR("%s", "Out of memory.");
590                 goto error_cleanup;
591             }
592         }
593     } while (substr != NULL);
594 
595     SAFE_FREE(stringdup);
596     return start_node;
597 error_cleanup:
598     SAFE_FREE(start_node);
599     SAFE_FREE(substr);
600     SAFE_FREE(stringdup);
601     return NULL;
602 }
603 
604 /** Free linked list of strings.
605  *
606  * @param[in] node the first node of the linked list.
607  */
608 void
free_string_list(NODE_STR_T * node)609 free_string_list(NODE_STR_T *node)
610 {
611     NODE_STR_T *next;
612     if (node == NULL)
613         return;
614     while (node != NULL) {
615         if (node->free_string)
616             free(node->str);
617         next = node->next;
618         free(node);
619         node = next;
620     }
621 }
622 
623 /** Free linked list of IFAPI objects.
624  *
625  * @param[in] node the first node of the linked list.
626  */
627 void
ifapi_free_object_list(NODE_OBJECT_T * node)628 ifapi_free_object_list(NODE_OBJECT_T *node)
629 {
630     NODE_OBJECT_T *next;
631     if (node == NULL)
632         return;
633     while (node != NULL) {
634         ifapi_cleanup_ifapi_object((IFAPI_OBJECT *)node->object);
635         SAFE_FREE(node->object);
636         next = node->next;
637         free(node);
638         node = next;
639     }
640 }
641 
642 /** Free linked list of IFAPI objects (link nodes only).
643  *
644  * @param[in] node the first node of the linked list.
645  */
646 void
ifapi_free_node_list(NODE_OBJECT_T * node)647 ifapi_free_node_list(NODE_OBJECT_T *node)
648 {
649     NODE_OBJECT_T *next;
650     if (node == NULL)
651         return;
652     while (node != NULL) {
653         next = node->next;
654         free(node);
655         node = next;
656     }
657 }
658 
659 /** Compute the number on nodes in a linked list.
660  *
661  * @param[in] node the first node of the linked list.
662  *
663  * @retval the number on nodes.
664  */
665 size_t
ifapi_path_length(NODE_STR_T * node)666 ifapi_path_length(NODE_STR_T *node)
667 {
668     size_t length = 0;
669     if (node == NULL)
670         return 0;
671     while (node != NULL) {
672         length += 1;
673         node = node->next;
674     }
675     return length;
676 }
677 
678 /** Compute the size of a concatenated string.
679  *
680  * @param[in] node the first node of the linked string list.
681  * @param[in] delim_length the size of the delimiter used for the concatenation.
682  *
683  * @retval the size of the string.
684  */
685 static size_t
path_str_length(NODE_STR_T * node,int delim_length)686 path_str_length(NODE_STR_T *node, int delim_length)
687 {
688     size_t size = 0;
689     if (node == NULL)
690         return 0;
691     while (node != NULL) {
692         size += strlen(node->str);
693         if (node->next != NULL)
694             size = size + delim_length;
695         node = node->next;
696     }
697     return size;
698 }
699 
700 /** Compute a pathname based on a linked list of strings.
701  *
702  * @param[out] dest The pointer to the generated pathname (callee allocated).
703  * @param[in]  supdir A sup directory will be the prefix of the pathname.
704  * @param[in]  node The linked list.
705  * @param[in]  name A name which is appended to the result if not NULL.
706  *
707  * @retval TSS2_RC_SUCCESS if the function call was a success.
708  * @retval TSS2_FAPI_RC_MEMORY if the memory for the pathname can't be allocated.
709  */
710 TSS2_RC
ifapi_path_string(char ** dest,const char * supdir,NODE_STR_T * node,char * name)711 ifapi_path_string(char **dest, const char *supdir, NODE_STR_T *node, char *name)
712 {
713     size_t length = 1 + path_str_length(node,
714                                         1) + ((supdir == NULL) ? 0 : strlen(supdir) + 1)
715                     + ((name == NULL) ? 0 : strlen(name) + 1);
716     *dest = malloc(length);
717     if (*dest == NULL) {
718         LOG_ERROR("Out of memory");
719         return TSS2_FAPI_RC_MEMORY;
720     }
721     *dest[0] = '\0';
722     if (supdir != NULL) {
723         strcat(*dest, supdir);
724         strcat(*dest, IFAPI_FILE_DELIM);
725     }
726     for (; node != NULL; node = node->next) {
727         strcat(*dest, node->str);
728         if (node->next != NULL) {
729             strcat(*dest, IFAPI_FILE_DELIM);
730         }
731     }
732     if (name != NULL) {
733         strcat(*dest, IFAPI_FILE_DELIM);
734         strcat(*dest, name);
735     }
736     return TSS2_RC_SUCCESS;
737 }
738 
739 
740 /** Compute a pathname based on the first n elements of a linked list of strings.
741  *
742  * @param[out] dest the pointer to the pathname (callee allocated).
743  * @param[in]  supdir a sup directory will be the prefix of the pathname.
744  *                    (can be NULL).
745  * @param[in]  node the linked list.
746  * @param[in]  name  the filename (can be NULL).
747  * @param[in]  n the number of the first elements which will bes used for concatenation.
748  * @retval TSS2_RC_SUCCESS if the function call was a success.
749  * @retval TSS2_FAPI_RC_MEMORY if the memory for the pathname can't be allocated.
750  */
751 TSS2_RC
ifapi_path_string_n(char ** dest,const char * supdir,NODE_STR_T * node,char * name,size_t n)752 ifapi_path_string_n(char **dest, const char *supdir, NODE_STR_T *node, char *name,
753                     size_t n)
754 {
755     size_t length = 1 + path_str_length(node,
756                                         1) + ((supdir == NULL) ? 0 : strlen(supdir) + 1)
757                     + ((name == NULL) ? 0 : strlen(name) + 1);
758     *dest = malloc(length);
759     size_t i;
760     if (*dest == NULL) {
761         LOG_ERROR("Out of memory");
762         return TSS2_FAPI_RC_MEMORY;
763     }
764     *dest[0] = '\0';
765     if (supdir != NULL) {
766         strcat(*dest, supdir);
767         strcat(*dest, IFAPI_FILE_DELIM);
768     }
769     for (i = 1; node != NULL && i <= n; i++, node = node->next) {
770         strcat(*dest, node->str);
771         if (node->next != NULL) {
772             strcat(*dest, IFAPI_FILE_DELIM);
773         }
774     }
775     if (name != NULL) {
776         strcat(*dest, IFAPI_FILE_DELIM);
777         strcat(*dest, name);
778     }
779     return TSS2_RC_SUCCESS;
780 }
781 
782 /** Initialize a linked list of strings.
783  *
784  * free string in the list object will be set to true.
785  * If the list will be extended by sub-string which are part
786  * of this strin free_string has to be set to false.
787  *
788  * @param[in] string The string for the first element.
789  *
790  * @retval the initial node of the linked list.
791  * @retval NULL if the list cannot be created.
792  */
793 NODE_STR_T *
init_string_list(const char * string)794 init_string_list(const char *string)
795 {
796     NODE_STR_T *result = malloc(sizeof(NODE_STR_T));
797     if (result == NULL)
798         return NULL;
799     result->next = NULL;
800     result->str = strdup(string);
801     if (result->str == NULL) {
802         LOG_ERROR("Out of memory");
803         free(result);
804         return NULL;
805     }
806     result->free_string = true;
807     return result;
808 }
809 
810 /** Add string to the last element of a linked list of strings.
811  *
812  * A duplicate of the passed string will be added.
813  *
814  * @param[in,out] str_list The linked list.
815  * @param[in] string The string to be added.
816  *
817  * @retval true if the string was added to the list.
818  * @retval false if the list could not be extended.
819  */
820 bool
add_string_to_list(NODE_STR_T * str_list,char * string)821 add_string_to_list(NODE_STR_T *str_list, char *string)
822 {
823     if (str_list == NULL)
824         return NULL;
825     NODE_STR_T *last = malloc(sizeof(NODE_STR_T));
826     if (last == NULL)
827         return false;
828     while (str_list->next != NULL)
829         str_list = str_list->next;
830     str_list->next = last;
831     last->next = NULL;
832     last->str = strdup(string);
833     return_if_null(last->str, "Out of memory.", false);
834     last->free_string = true;
835     return true;
836 }
837 
838 /** Add a object as first element to a linked list.
839  *
840  * @param[in] object The object to be added.
841  * @param[in,out] object_list The linked list to be extended.
842  *
843  * @retval TSS2_RC_SUCCESS if the object was added.
844  * @retval TSS2_FAPI_RC_MEMORY If memory for the list extension cannot
845  *         be allocated.
846  */
847 TSS2_RC
push_object_to_list(void * object,NODE_OBJECT_T ** object_list)848 push_object_to_list(void *object, NODE_OBJECT_T **object_list)
849 {
850     NODE_OBJECT_T *first = calloc(1, sizeof(NODE_OBJECT_T));
851     return_if_null(first, "Out of space.", TSS2_FAPI_RC_MEMORY);
852     first->object = object;
853     if (*object_list)
854         first->next = *object_list;
855     *object_list = first;
856     return TSS2_RC_SUCCESS;
857 }
858 
859 /** Add a object as last element to a linked list.
860  *
861  * @param[in] object The object to be added.
862  * @param[in,out] object_list The linked list to be extended.
863  *
864  * @retval TSS2_RC_SUCCESS if the object was added.
865  * @retval TSS2_FAPI_RC_MEMORY If memory for the list extension cannot
866  *         be allocated.
867  */
868 TSS2_RC
append_object_to_list(void * object,NODE_OBJECT_T ** object_list)869 append_object_to_list(void *object, NODE_OBJECT_T **object_list)
870 {
871     NODE_OBJECT_T *list, *last = calloc(1, sizeof(NODE_OBJECT_T));
872     return_if_null(last, "Out of space.", TSS2_FAPI_RC_MEMORY);
873     last->object = object;
874     if (!*object_list) {
875         *object_list = last;
876         return TSS2_RC_SUCCESS;
877     }
878     list = *object_list;
879     while (list->next)
880         list = list->next;
881     list->next = last;
882     return TSS2_RC_SUCCESS;
883 }
884 
885 /** Initialize the internal representation of a FAPI hierarchy object.
886  *
887  * The object will be cleared and the type of the general fapi object will be
888  * set to hierarchy.
889  *
890  * @param[out] hierarchy The caller allocated hierarchy object.
891  * @param[in] esys_handle The ESAPI handle of the hierarchy which will be added to
892  *            to the object.
893  */
894 void
ifapi_init_hierarchy_object(IFAPI_OBJECT * hierarchy,ESYS_TR esys_handle)895 ifapi_init_hierarchy_object(
896     IFAPI_OBJECT *hierarchy,
897     ESYS_TR esys_handle)
898 {
899     memset(hierarchy, 0, sizeof(IFAPI_OBJECT));
900     hierarchy->system = TPM2_YES;
901     hierarchy->objectType = IFAPI_HIERARCHY_OBJ;
902     hierarchy->handle = esys_handle;
903 }
904 
905 /** Get description of a FAPI object.
906  *
907  * @param[in] object The object which might have a description.
908  *
909  * @retval The character description of the object.
910  * @retval NULL if no description is available.
911  */
912 char *
get_description(IFAPI_OBJECT * object)913 get_description(IFAPI_OBJECT *object)
914 {
915     switch (object->objectType) {
916     case IFAPI_KEY_OBJ:
917         return object->misc.key.description;
918     case IFAPI_NV_OBJ:
919         return object->misc.nv.description;
920     default:
921         return NULL;
922     }
923 }
924 
925 /** Create a directory and all sub directories.
926  *
927  * @param[in] supdir The sup directory were the directories will be created.
928  * @param[in] dir_list A linked list with the directory strings.
929  * @param[in] mode The creation mode for the directory which will be used
930  *            for the mkdir function.
931  * @retval TSS2_RC_SUCCESS on success.
932  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
933  *         the function.
934  */
935 static TSS2_RC
create_dirs(const char * supdir,NODE_STR_T * dir_list,mode_t mode)936 create_dirs(const char *supdir, NODE_STR_T *dir_list, mode_t mode)
937 {
938     char *new_dir;
939     for (size_t i = 1; i <= ifapi_path_length(dir_list); i++) {
940         TSS2_RC r = ifapi_path_string_n(&new_dir, supdir, dir_list, NULL, i);
941         return_if_error(r, "Create path string");
942         LOG_TRACE("Check file: %s", new_dir);
943         int rc = mkdir(new_dir, mode);
944         if (rc != 0 && errno != EEXIST) {
945             LOG_ERROR("mkdir not possible: %i %s", rc, new_dir);
946             free(new_dir);
947             return TSS2_FAPI_RC_BAD_VALUE;
948         }
949         free(new_dir);
950     }
951     return TSS2_RC_SUCCESS;
952 }
953 
954 /** Create sub-directories in a certain directory.
955  *
956  * @param[in] supdir The directory in which the new directories shall be created.
957  * @param[in] path The path containing one or more sub-directories.
958  *
959  * @retval TSS2_RC_SUCCESS: If the directories were created.
960  * @retval TSS2_FAPI_RC_MEMORY: If the linked list with the sub-directories
961  *                              cannot be allocated.
962  * @retval TSS2_FAPI_RC_BAD_VALUE: If a directory cannot be created.
963  */
964 TSS2_RC
ifapi_create_dirs(const char * supdir,const char * path)965 ifapi_create_dirs(const char *supdir, const char *path)
966 {
967     TSS2_RC r;
968     NODE_STR_T *path_list = split_string(path, IFAPI_FILE_DELIM);
969     return_if_null(path_list, "Out of memory.", TSS2_FAPI_RC_MEMORY);
970 
971     r = create_dirs(supdir, path_list, 0777);
972     goto_if_error2(r, "Create directories for %s", error_cleanup, path);
973     free_string_list(path_list);
974     return TSS2_RC_SUCCESS;
975 
976 error_cleanup:
977     free_string_list(path_list);
978     return r;
979 }
980 
981 /** Determine whether authentication with an auth value is needed ro an object..
982  *
983  * In the key store the information whether an auth value was provided for an
984  * object is saved. Thus the it is possible to decide whether the auth value
985  * callback is required for authentication.
986  *
987  * @param[in] object The object which has to be checked..
988  *
989  * @retval true: If an auth value was provided.
990  * @retval false: If not.
991  */
992 bool
object_with_auth(IFAPI_OBJECT * object)993 object_with_auth(IFAPI_OBJECT *object)
994 {
995     switch (object->objectType) {
996     case IFAPI_KEY_OBJ:
997         return (object->misc.key.with_auth == TPM2_YES);
998     case IFAPI_NV_OBJ:
999         return (object->misc.nv.with_auth == TPM2_YES);
1000     case IFAPI_HIERARCHY_OBJ:
1001         return (object->misc.hierarchy.with_auth == TPM2_YES);
1002     default:
1003         return false;
1004     }
1005 }
1006 
1007 /** Free memory allocated during deserialization of a policy element.
1008  *
1009  * Depending on the element type the fields of a policy element are freed.
1010  *
1011  * @param[in] policy The policy element.
1012  */
1013 static void
cleanup_policy_element(TPMT_POLICYELEMENT * policy)1014 cleanup_policy_element(TPMT_POLICYELEMENT *policy)
1015 {
1016         switch (policy->type) {
1017         case POLICYSECRET:
1018             SAFE_FREE(policy->element.PolicySecret.objectPath);
1019             break;
1020         case POLICYAUTHORIZE:
1021             SAFE_FREE(policy->element.PolicyAuthorize.keyPath);
1022             SAFE_FREE(policy->element.PolicyAuthorize.keyPEM);
1023             break;
1024         case POLICYAUTHORIZENV:
1025             SAFE_FREE( policy->element.PolicyAuthorizeNv.nvPath);
1026             SAFE_FREE( policy->element.PolicyAuthorizeNv.policy_buffer);
1027             break;
1028         case POLICYSIGNED:
1029             SAFE_FREE(policy->element.PolicySigned.keyPath);
1030             SAFE_FREE(policy->element.PolicySigned.keyPEM);
1031             SAFE_FREE(policy->element.PolicySigned.publicKeyHint);
1032             break;
1033         case POLICYPCR:
1034             SAFE_FREE(policy->element.PolicyPCR.pcrs);
1035             break;
1036         case POLICYNV:
1037             SAFE_FREE(policy->element.PolicyNV.nvPath);
1038             break;
1039         case POLICYDUPLICATIONSELECT:
1040             SAFE_FREE(policy->element.PolicyDuplicationSelect.newParentPath);
1041             break;
1042         case POLICYNAMEHASH:
1043             for (size_t i = 0; i < 3; i++) {
1044                 SAFE_FREE(policy->element.PolicyNameHash.namePaths[i]);
1045             }
1046             break;
1047         case POLICYACTION:
1048             SAFE_FREE(policy->element.PolicyAction.action);
1049             break;
1050         }
1051 }
1052 
1053 /** Free memory allocated during deserialization of a a policy element list.
1054  *
1055  * All elements of a policy element list are freed.
1056  *
1057  * @param[in] policy The policy element list.
1058  */
1059 static void
cleanup_policy_elements(TPML_POLICYELEMENTS * policy)1060 cleanup_policy_elements(TPML_POLICYELEMENTS *policy)
1061 {
1062     size_t i, j;
1063     if (policy != NULL) {
1064         for (i = 0; i < policy->count; i++) {
1065             if (policy->elements[i].type == POLICYOR) {
1066                 /* Policy with sub policies */
1067                 TPML_POLICYBRANCHES *branches = policy->elements[i].element.PolicyOr.branches;
1068                 for (j = 0; j < branches->count; j++) {
1069                     SAFE_FREE(branches->authorizations[j].name);
1070                     SAFE_FREE(branches->authorizations[j].description);
1071                     cleanup_policy_elements(branches->authorizations[j].policy);
1072                 }
1073                 SAFE_FREE(branches);
1074             } else {
1075                 cleanup_policy_element(&policy->elements[i]);
1076             }
1077         }
1078         SAFE_FREE(policy);
1079     }
1080 }
1081 
1082 /** Free memory allocated during deserialization of policy.
1083  *
1084  * The object will not be freed (might be declared on the stack).
1085  *
1086  * @param[in] policy The policy to be cleaned up.
1087  *
1088  */
1089 void
ifapi_cleanup_policy(TPMS_POLICY * policy)1090 ifapi_cleanup_policy(TPMS_POLICY *policy)
1091 {
1092     if (policy) {
1093         SAFE_FREE(policy->description);
1094         if (policy->policyAuthorizations) {
1095             for (size_t i = 0; i < policy->policyAuthorizations->count; i++) {
1096                 SAFE_FREE(policy->policyAuthorizations->authorizations[i].type);
1097             }
1098         }
1099         SAFE_FREE(policy->policyAuthorizations);
1100         cleanup_policy_elements(policy->policy);
1101     }
1102 }
1103 
1104 /** Free memory of a policy object.
1105  *
1106  * The memory allocated during deserialization of the policy will
1107  * also be freed.
1108  *
1109  * @param[in] object The policy object to be cleaned up.
1110  *
1111  */
1112 static void
cleanup_policy_object(POLICY_OBJECT * object)1113 cleanup_policy_object(POLICY_OBJECT * object) {
1114     if (object != NULL) {
1115         SAFE_FREE(object->path);
1116         ifapi_cleanup_policy(&object->policy);
1117         cleanup_policy_object(object->next);
1118     }
1119 }
1120 
1121 static TPML_POLICYELEMENTS *
1122 copy_policy_elements(const TPML_POLICYELEMENTS *from_policy);
1123 
1124 /** Copy policy structure.
1125  *
1126  * @param[in] src The policy structure to be copied.
1127  * @param[out] dest The destination policy structure.
1128  * @retval TSS2_RC_SUCCESS on success.
1129  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1130  */
1131 static TSS2_RC
copy_policy(TPMS_POLICY * dest,const TPMS_POLICY * src)1132 copy_policy(TPMS_POLICY * dest,
1133         const TPMS_POLICY * src) {
1134     /* Check for NULL references */
1135     if (dest == NULL || src == NULL) {
1136         return TSS2_FAPI_RC_MEMORY;
1137     }
1138 
1139     TSS2_RC r = TSS2_RC_SUCCESS;
1140     dest->description = NULL;
1141     strdup_check(dest->description, src->description, r, error_cleanup);
1142     dest->policy = copy_policy_elements(src->policy);
1143     goto_if_null2(dest->policy, "Out of memory", r, TSS2_FAPI_RC_MEMORY,
1144             error_cleanup);
1145 
1146     return r;
1147 error_cleanup:
1148     ifapi_cleanup_policy(dest);
1149     return r;
1150 }
1151 
1152 /** Copy policy object.
1153  *
1154  * @param[in] src The policy object to be copied.
1155  * @param[out] dest The destination policy object.
1156  * @retval TSS2_RC_SUCCESS on success.
1157  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1158  */
1159 static TSS2_RC
copy_policy_object(POLICY_OBJECT * dest,const POLICY_OBJECT * src)1160 copy_policy_object(POLICY_OBJECT * dest, const POLICY_OBJECT * src) {
1161     /* Check for NULL references */
1162     if (dest == NULL || src == NULL) {
1163         return TSS2_FAPI_RC_MEMORY;
1164     }
1165 
1166     TSS2_RC r = TSS2_RC_SUCCESS;
1167     dest->policy.description = NULL;
1168     dest->policy.policyAuthorizations = NULL;
1169     dest->policy.policy = NULL;
1170     strdup_check(dest->path, src->path, r, error_cleanup);
1171     r = copy_policy(&dest->policy, &src->policy);
1172     goto_if_error(r, "Could not copy policy", error_cleanup);
1173     if (src->next != NULL) {
1174         dest->next = malloc(sizeof(POLICY_OBJECT));
1175         goto_if_null(dest->next, "Out of memory", r, error_cleanup);
1176         dest->next->next = NULL;
1177         r = copy_policy_object(dest->next, src->next);
1178         goto_if_error(r, "Could not copy next policy object", error_cleanup);
1179     }
1180 
1181     return r;
1182 error_cleanup:
1183     cleanup_policy_object(dest);
1184     return r;
1185 }
1186 
1187 /** Copy policy authorization.
1188  *
1189  * @param[in] src The policy authorization to be copied.
1190  * @param[out] dest The destination policy authorization.
1191  * @retval TSS2_RC_SUCCESS on success.
1192  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1193  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1194  */
1195 static TSS2_RC
copy_policyauthorization(TPMS_POLICYAUTHORIZATION * dest,const TPMS_POLICYAUTHORIZATION * src)1196 copy_policyauthorization(TPMS_POLICYAUTHORIZATION * dest,
1197         const TPMS_POLICYAUTHORIZATION * src) {
1198     if (dest == NULL || src == NULL) {
1199         return TSS2_FAPI_RC_BAD_REFERENCE;
1200     }
1201     TSS2_RC r = TSS2_RC_SUCCESS;
1202     strdup_check(dest->type, src->type, r, error_cleanup);
1203 
1204     dest->key = src->key;
1205     dest->policyRef = src->policyRef;
1206     dest->signature = src->signature;
1207 
1208     return r;
1209 error_cleanup:
1210     SAFE_FREE(dest->type);
1211     return r;
1212 }
1213 
1214 /** Copy policy branches.
1215  *
1216  * @param[in] src The policy branches to be copied.
1217  * @param[out] dest The destination policy branches.
1218  * @retval TSS2_RC_SUCCESS on success.
1219  */
1220 static TPML_POLICYBRANCHES *
copy_policy_branches(const TPML_POLICYBRANCHES * from_branches)1221 copy_policy_branches(const TPML_POLICYBRANCHES *from_branches)
1222 {
1223     TPML_POLICYBRANCHES *to_branches;
1224     size_t j;
1225 
1226     to_branches = calloc(1, sizeof(TPML_POLICYBRANCHES) +
1227                          from_branches->count * sizeof(TPMS_POLICYBRANCH));
1228     if (!to_branches)
1229         return NULL;
1230     to_branches->count = from_branches->count;
1231     for (j = 0; j < from_branches->count; j++) {
1232         to_branches->authorizations[j].name = strdup(from_branches->authorizations[j].name);
1233         if (!to_branches->authorizations[j].name)
1234             goto error;
1235         to_branches->authorizations[j].description =
1236             strdup(from_branches->authorizations[j].description);
1237         if (!to_branches->authorizations[j].description)
1238             goto error;
1239         to_branches->authorizations[j].policy =
1240             copy_policy_elements(from_branches->authorizations[j].policy);
1241         if (to_branches->authorizations[j].policy == NULL
1242             && from_branches->authorizations[j].policy != NULL) {
1243             LOG_ERROR("Out of memory.");
1244             goto error;
1245         }
1246         to_branches->authorizations[j].policyDigests =
1247             from_branches->authorizations[j].policyDigests;
1248     }
1249     return to_branches;
1250 
1251 error:
1252     for (j = 0; j < to_branches->count; j++) {
1253         SAFE_FREE(to_branches->authorizations[j].name);
1254         SAFE_FREE(to_branches->authorizations[j].description);
1255         cleanup_policy_elements(to_branches->authorizations[j].policy);
1256     }
1257     SAFE_FREE(to_branches);
1258     return NULL;
1259 }
1260 
1261 /** Create a copy of a policy element.
1262  *
1263  * Depending on the type of a poliy element a copy with newly allocated memory will be
1264  * created.
1265  *
1266  * @param[in]  from_policy The policy to be copied.
1267  * @param[out] to_policy The new policy element.
1268  *
1269  * @retval TSS2_RC_SUCCESS: if copying was successful.
1270  * @retval TSS2_FAPI_RC_BAD_REFERENCE: If no from policy or no to policy was passed.
1271  * @retval TSS2_FAPI_RC_MEMORY: If not enough memory can be allocated.
1272  */
1273 static TSS2_RC
copy_policy_element(const TPMT_POLICYELEMENT * from_policy,TPMT_POLICYELEMENT * to_policy)1274 copy_policy_element(const TPMT_POLICYELEMENT *from_policy, TPMT_POLICYELEMENT *to_policy)
1275 {
1276     if (from_policy == NULL || to_policy == NULL) {
1277         return TSS2_FAPI_RC_BAD_REFERENCE;
1278     }
1279     TSS2_RC r = TSS2_RC_SUCCESS;
1280 
1281     *to_policy = *from_policy;
1282     size_t i;
1283 
1284     switch (from_policy->type) {
1285     case POLICYSECRET:
1286         strdup_check(to_policy->element.PolicySecret.objectPath,
1287                      from_policy->element.PolicySecret.objectPath, r, error);
1288         break;
1289     case POLICYAUTHORIZE:
1290         strdup_check(to_policy->element.PolicyAuthorize.keyPath,
1291                      from_policy->element.PolicyAuthorize.keyPath, r, error);
1292         strdup_check(to_policy->element.PolicyAuthorize.keyPEM,
1293                      from_policy->element.PolicyAuthorize.keyPEM, r, error);
1294         if (from_policy->element.PolicyAuthorize.policy_list) {
1295             to_policy->element.PolicyAuthorize.policy_list =
1296                 malloc(sizeof(POLICY_OBJECT));
1297             goto_if_null2(to_policy->element.PolicyAuthorize.policy_list,
1298                           "Out of memory", r, TSS2_FAPI_RC_MEMORY, error);
1299             to_policy->element.PolicyAuthorize.policy_list->next = NULL;
1300             r = copy_policy_object(to_policy->element.PolicyAuthorize.policy_list,
1301                                    from_policy->element.PolicyAuthorize.policy_list);
1302             goto_if_error(r, "Could not copy policy list", error);
1303 
1304         }
1305         if (from_policy->element.PolicyAuthorize.authorization) {
1306             to_policy->element.PolicyAuthorize.authorization =
1307                 malloc(sizeof(TPMS_POLICYAUTHORIZATION));
1308             goto_if_null(to_policy->element.PolicyAuthorize.authorization,
1309                          "Out of memory", r, error);
1310             r = copy_policyauthorization(to_policy->element.PolicyAuthorize.authorization,
1311                                          from_policy->element.PolicyAuthorize.authorization);
1312             goto_if_error(r, "Could not copy policy authorization", error);
1313         }
1314         break;
1315     case POLICYAUTHORIZENV:
1316         strdup_check(to_policy->element.PolicyAuthorizeNv.nvPath,
1317                      from_policy->element.PolicyAuthorizeNv.nvPath, r, error);
1318         break;
1319     case POLICYSIGNED:
1320         strdup_check(to_policy->element.PolicySigned.keyPath,
1321                      from_policy->element.PolicySigned.keyPath, r, error);
1322         strdup_check(to_policy->element.PolicySigned.keyPEM,
1323                      from_policy->element.PolicySigned.keyPEM, r, error);
1324         strdup_check(to_policy->element.PolicySigned.publicKeyHint,
1325                      from_policy->element.PolicySigned.publicKeyHint, r, error);
1326         break;
1327     case POLICYPCR:
1328         to_policy->element.PolicyPCR.pcrs =
1329             calloc(1, sizeof(TPML_PCRVALUES) +
1330                    from_policy->element.PolicyPCR.pcrs->count + sizeof(TPMS_PCRVALUE));
1331         goto_if_null2(to_policy->element.PolicyPCR.pcrs, "Out of memory.",
1332                       r, TSS2_FAPI_RC_MEMORY, error);
1333         to_policy->element.PolicyPCR.pcrs->count
1334             = from_policy->element.PolicyPCR.pcrs->count;
1335         for (i = 0; i < to_policy->element.PolicyPCR.pcrs->count; i++)
1336             to_policy->element.PolicyPCR.pcrs->pcrs[i]
1337                 = from_policy->element.PolicyPCR.pcrs->pcrs[i];
1338         break;
1339     case POLICYNV:
1340         strdup_check(to_policy->element.PolicyNV.nvPath,
1341                      from_policy->element.PolicyNV.nvPath, r, error);
1342         break;
1343     case POLICYDUPLICATIONSELECT:
1344         strdup_check(to_policy->element.PolicyDuplicationSelect.newParentPath,
1345                      from_policy->element.PolicyDuplicationSelect.newParentPath,
1346                      r, error);
1347         break;
1348     case POLICYNAMEHASH:
1349         for (size_t i = 0; i < from_policy->element.PolicyNameHash.count; i++) {
1350             strdup_check(to_policy->element.PolicyNameHash.namePaths[i],
1351                     from_policy->element.PolicyNameHash.namePaths[i],
1352                     r, error);
1353         }
1354         break;
1355     case POLICYOR:
1356         to_policy->element.PolicyOr.branches =
1357             copy_policy_branches(from_policy->element.PolicyOr.branches);
1358         goto_if_null2(to_policy->element.PolicyOr.branches, "Out of memory",
1359                       r, TSS2_FAPI_RC_MEMORY, error);
1360         break;
1361     }
1362     return TSS2_RC_SUCCESS;
1363 
1364 error:
1365     return r;
1366 }
1367 
1368 /** Copy a list of policy elements
1369  *
1370  * @param[in] form_policy The policy list to be copied.
1371  * @retval NULL If the policy cannot be copied.
1372  * @retval TPML_POLICYELEMENTS The copy of the policy list.
1373  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1374  */
1375 static TPML_POLICYELEMENTS *
copy_policy_elements(const TPML_POLICYELEMENTS * from_policy)1376 copy_policy_elements(const TPML_POLICYELEMENTS *from_policy)
1377 {
1378     if (from_policy == NULL) {
1379         return NULL;
1380     }
1381     TSS2_RC r;
1382     size_t i;
1383     TPML_POLICYELEMENTS *to_policy = NULL;
1384 
1385     to_policy = calloc(1, sizeof(TPML_POLICYELEMENTS) +
1386                        from_policy->count * sizeof(TPMT_POLICYELEMENT));
1387     to_policy->count = from_policy->count;
1388     for (i = 0; i < from_policy->count; i++) {
1389         if (from_policy->elements[i].type == POLICYOR) {
1390             to_policy->elements[i].type = POLICYOR;
1391             /* Policy with sub policies */
1392             TPML_POLICYBRANCHES *branches = from_policy->elements[i].element.PolicyOr.branches;
1393             to_policy->elements[i].element.PolicyOr.branches = copy_policy_branches(branches);
1394             if (to_policy->elements[i].element.PolicyOr.branches == NULL) {
1395                 LOG_ERROR("Out of memory");
1396                 SAFE_FREE(to_policy);
1397                 return NULL;
1398             }
1399         } else {
1400             r = copy_policy_element(&from_policy->elements[i], &to_policy->elements[i]);
1401             if (r != TSS2_RC_SUCCESS) {
1402                 cleanup_policy_elements(to_policy);
1403                 return NULL;
1404             }
1405         }
1406     }
1407     return to_policy;
1408 }
1409 
1410 /** Copy policy.
1411  *
1412  * @param[in] from_policy the policy to be copied.
1413  * @retval The new policy or NULL if not enough memory was available.
1414  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1415  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1416  */
1417 TPMS_POLICY *
ifapi_copy_policy(const TPMS_POLICY * from_policy)1418 ifapi_copy_policy(
1419     const TPMS_POLICY *from_policy)
1420 {
1421     if (from_policy == NULL) {
1422         return NULL;
1423     }
1424     TPMS_POLICY *to_policy = calloc(1, sizeof(TPMS_POLICY));
1425     if (to_policy == NULL) {
1426         return NULL;
1427     }
1428     to_policy->description = NULL;
1429     TSS2_RC r = copy_policy(to_policy, from_policy);
1430     if (r != TSS2_RC_SUCCESS) {
1431         SAFE_FREE(to_policy);
1432         return NULL;
1433     } else {
1434         return to_policy;
1435     }
1436 }
1437 
1438 /** Compute the name of a TPM transient or persistent object.
1439  *
1440  * @param[in] publicInfo The public information of the TPM object.
1441  * @param[out] name The computed name.
1442  * @retval TPM2_RC_SUCCESS  or one of the possible errors TSS2_FAPI_RC_BAD_VALUE,
1443  * TSS2_FAPI_RC_MEMORY, TSS2_FAPI_RC_GENERAL_FAILURE.
1444  * or return codes of SAPI errors.
1445  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1446  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1447  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
1448  *         the function.
1449  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
1450  */
1451 TSS2_RC
ifapi_get_name(TPMT_PUBLIC * publicInfo,TPM2B_NAME * name)1452 ifapi_get_name(TPMT_PUBLIC *publicInfo, TPM2B_NAME *name)
1453 {
1454     BYTE buffer[sizeof(TPMT_PUBLIC)];
1455     size_t offset = 0;
1456     size_t len_alg_id = sizeof(TPMI_ALG_HASH);
1457     size_t size = sizeof(TPMU_NAME) - sizeof(TPMI_ALG_HASH);
1458     IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext;
1459 
1460     if (publicInfo->nameAlg == TPM2_ALG_NULL) {
1461         name->size = 0;
1462         return TSS2_RC_SUCCESS;
1463     }
1464     TSS2_RC r;
1465     r = ifapi_crypto_hash_start(&cryptoContext, publicInfo->nameAlg);
1466     return_if_error(r, "crypto hash start");
1467 
1468     r = Tss2_MU_TPMT_PUBLIC_Marshal(publicInfo,
1469                                     &buffer[0], sizeof(TPMT_PUBLIC), &offset);
1470     if (r) {
1471         LOG_ERROR("Marshaling TPMT_PUBLIC");
1472         ifapi_crypto_hash_abort(&cryptoContext);
1473         return r;
1474     }
1475 
1476     r = ifapi_crypto_hash_update(cryptoContext, &buffer[0], offset);
1477     if (r) {
1478         LOG_ERROR("crypto hash update");
1479         ifapi_crypto_hash_abort(&cryptoContext);
1480         return r;
1481     }
1482 
1483     r = ifapi_crypto_hash_finish(&cryptoContext, &name->name[len_alg_id],
1484                                  &size);
1485     if (r) {
1486         LOG_ERROR("crypto hash finish");
1487         ifapi_crypto_hash_abort(&cryptoContext);
1488         return r;
1489     }
1490 
1491     offset = 0;
1492     r = Tss2_MU_TPMI_ALG_HASH_Marshal(publicInfo->nameAlg,
1493                                       &name->name[0], sizeof(TPMI_ALG_HASH),
1494                                       &offset);
1495     return_if_error(r, "Marshaling TPMI_ALG_HASH");
1496 
1497     name->size = size + len_alg_id;
1498     return TSS2_RC_SUCCESS;
1499 }
1500 
1501 /** Compute the name from the public data of a NV index.
1502  *
1503  * The name of a NV index is computed as follows:
1504  *   name = nameAlg||Hash(nameAlg,marshal(publicArea))
1505  * @param[in] publicInfo The public information of the NV index.
1506  * @param[out] name The computed name.
1507  * @retval TSS2_RC_SUCCESS on success.
1508  * @retval TSS2_FAPI_RC_MEMORY Memory can not be allocated.
1509  * @retval TSS2_FAPI_RC_BAD_VALUE for invalid parameters.
1510  * @retval TSS2_FAPI_RC_BAD_REFERENCE for unexpected NULL pointer parameters.
1511  * @retval TSS2_FAPI_RC_GENERAL_FAILURE for errors of the crypto library.
1512  * @retval TSS2_SYS_RC_* for SAPI errors.
1513  */
1514 TSS2_RC
ifapi_nv_get_name(TPM2B_NV_PUBLIC * publicInfo,TPM2B_NAME * name)1515 ifapi_nv_get_name(TPM2B_NV_PUBLIC *publicInfo, TPM2B_NAME *name)
1516 {
1517     BYTE buffer[sizeof(TPMS_NV_PUBLIC)];
1518     size_t offset = 0;
1519     size_t size = sizeof(TPMU_NAME) - sizeof(TPMI_ALG_HASH);
1520     size_t len_alg_id = sizeof(TPMI_ALG_HASH);
1521     IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext;
1522 
1523     if (publicInfo->nvPublic.nameAlg == TPM2_ALG_NULL) {
1524         name->size = 0;
1525         return TSS2_RC_SUCCESS;
1526     }
1527     TSS2_RC r;
1528 
1529     /* Initialize the hash computation with the nameAlg. */
1530     r = ifapi_crypto_hash_start(&cryptoContext, publicInfo->nvPublic.nameAlg);
1531     return_if_error(r, "Crypto hash start");
1532 
1533     /* Get the marshaled data of the public area. */
1534     r = Tss2_MU_TPMS_NV_PUBLIC_Marshal(&publicInfo->nvPublic,
1535                                        &buffer[0], sizeof(TPMS_NV_PUBLIC),
1536                                        &offset);
1537     if (r) {
1538         LOG_ERROR("Marshaling TPMS_NV_PUBLIC");
1539         ifapi_crypto_hash_abort(&cryptoContext);
1540         return r;
1541     }
1542 
1543     r = ifapi_crypto_hash_update(cryptoContext, &buffer[0], offset);
1544     if (r) {
1545         LOG_ERROR("crypto hash update");
1546         ifapi_crypto_hash_abort(&cryptoContext);
1547         return r;
1548     }
1549 
1550     /* The hash will be stored after the nameAlg.*/
1551     r = ifapi_crypto_hash_finish(&cryptoContext, &name->name[len_alg_id],
1552                                  &size);
1553     if (r) {
1554         LOG_ERROR("crypto hash finish");
1555         ifapi_crypto_hash_abort(&cryptoContext);
1556         return r;
1557     }
1558 
1559     offset = 0;
1560     /* Store the nameAlg in the result. */
1561     r = Tss2_MU_TPMI_ALG_HASH_Marshal(publicInfo->nvPublic.nameAlg,
1562                                       &name->name[0], sizeof(TPMI_ALG_HASH),
1563                                       &offset);
1564     return_if_error(r, "Marshaling TPMI_ALG_HASH");
1565 
1566     name->size = size + len_alg_id;
1567     return TSS2_RC_SUCCESS;
1568 }
1569 
1570 /** Check whether a nv or key object has a certain name.
1571  *
1572  * @param[in] object The object (has to be checked whether it's a key).
1573  * @param[in] name The name to be compared.
1574  * @param[out] equal If the two names are equal.
1575  * @retval TSS2_RC_SUCCESSS if name of object can be deserialized.
1576  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1577  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1578  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
1579  *         the function.
1580  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
1581  */
1582 TSS2_RC
ifapi_object_cmp_name(IFAPI_OBJECT * object,void * name,bool * equal)1583 ifapi_object_cmp_name(IFAPI_OBJECT *object, void *name, bool *equal)
1584 {
1585     TSS2_RC r;
1586     *equal = false;
1587     TPM2B_NAME *obj_name;
1588     TPM2B_NAME nv_name;
1589 
1590     switch (object->objectType) {
1591     case IFAPI_KEY_OBJ:
1592         obj_name = &object->misc.key.name;
1593         break;
1594     case IFAPI_NV_OBJ:
1595         r = ifapi_nv_get_name(&object->misc.nv.public, &nv_name);
1596         return_if_error(r, "Get NV name.");
1597 
1598         obj_name = &nv_name;
1599         break;
1600     default:
1601         return TSS2_RC_SUCCESS;
1602     }
1603     if (obj_name->size != ((TPM2B_NAME *)name)->size)
1604         return TSS2_RC_SUCCESS;
1605     if (memcmp(&obj_name->name[0], &((TPM2B_NAME *)name)->name[0], obj_name->size))
1606         /* The names are not equal */
1607         return TSS2_RC_SUCCESS;
1608     /* The two names are equal */
1609     *equal = true;
1610     return TSS2_RC_SUCCESS;
1611 }
1612 
1613 /** Check whether a nv object has a certain public info.
1614  *
1615  * @param[in] object The object (has to be checked whether it's a key).
1616  * @param[in] nv_public The NV public data with the NV index.
1617  * @param[out] equal If the two names are equal.
1618  * @retval TSS2_RC_SUCCESSS if name of object can be deserialized.
1619  */
1620 TSS2_RC
ifapi_object_cmp_nv_public(IFAPI_OBJECT * object,void * nv_public,bool * equal)1621 ifapi_object_cmp_nv_public(IFAPI_OBJECT *object, void *nv_public, bool *equal)
1622 {
1623     *equal = false;
1624 
1625     switch (object->objectType) {
1626         break;
1627     case IFAPI_NV_OBJ:
1628         if (object->misc.nv.public.nvPublic.nvIndex
1629             == ((TPM2B_NV_PUBLIC *)nv_public)->nvPublic.nvIndex)
1630             *equal = true;
1631         break;
1632     default:
1633         return TSS2_RC_SUCCESS;
1634     }
1635     return TSS2_RC_SUCCESS;
1636 }
1637 
1638 /** Compute signature as byte array and signature size in DER format.
1639  *
1640  * For ECC signatures the conversion to DER is necessary, for RSA the
1641  * buffer of the TPM2B has already DER format.
1642  * parameters.
1643  * @param[in] sig_key_object The signing key.
1644  * @param[in] tpm_signature the signature in TPM format.
1645  * @param[out] signature The byte array of the signature (callee allocated).
1646  * @param[out] signatureSize The size of the byte array.
1647  *
1648  * @retval TSS2_RC_SUCCESSS if the conversion was successful.
1649  * @retval TSS2_FAPI_RC_MEMORY: if not enough memory can be allocated.
1650  * @retval TSS2_FAPI_RC_GENERAL_FAILURE If an internal error occurs, which is
1651  *         not covered by other return codes (e.g. a unexpected openssl
1652  *         error).
1653  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
1654  *         the function.
1655  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1656  */
1657 TSS2_RC
ifapi_tpm_to_fapi_signature(IFAPI_OBJECT * sig_key_object,TPMT_SIGNATURE * tpm_signature,uint8_t ** signature,size_t * signatureSize)1658 ifapi_tpm_to_fapi_signature(
1659     IFAPI_OBJECT *sig_key_object,
1660     TPMT_SIGNATURE *tpm_signature,
1661     uint8_t **signature,
1662     size_t *signatureSize)
1663 {
1664     TSS2_RC r;
1665 
1666     *signature = NULL;
1667     TPMT_SIG_SCHEME *sig_scheme = &sig_key_object->misc.key.signing_scheme;
1668 
1669     if (sig_key_object->misc.key.public.publicArea.type == TPM2_ALG_RSA) {
1670         /* Signature is already in DER format. */
1671 
1672         if (sig_scheme->scheme == TPM2_ALG_RSAPSS) {
1673             *signatureSize = tpm_signature->signature.rsapss.sig.size;
1674             *signature = malloc(*signatureSize);
1675             goto_if_null(*signature, "Out of memory.", TSS2_FAPI_RC_MEMORY, error_cleanup);
1676 
1677             memcpy(*signature,
1678                    &tpm_signature->signature.rsapss.sig.buffer[0],
1679                    *signatureSize);
1680         } else if (sig_scheme->scheme == TPM2_ALG_RSASSA) {
1681             *signatureSize = tpm_signature->signature.rsassa.sig.size;
1682             *signature = malloc(*signatureSize);
1683             goto_if_null(*signature, "Out of memory.", TSS2_FAPI_RC_MEMORY, error_cleanup);
1684 
1685             memcpy(*signature,
1686                    &tpm_signature->signature.rsassa.sig.buffer[0],
1687                    *signatureSize);
1688         }
1689     } else if (sig_key_object->misc.key.public.publicArea.type == TPM2_ALG_ECC &&
1690                sig_scheme->scheme == TPM2_ALG_ECDSA) {
1691         /* For ECC signatures the TPM signaute has to be converted to DER. */
1692         r = ifapi_tpm_ecc_sig_to_der(tpm_signature,
1693                                      signature, signatureSize);
1694         goto_if_error(r, "Conversion to DER failed", error_cleanup);
1695     } else {
1696         goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Unknown signature scheme", error_cleanup);
1697     }
1698     return TSS2_RC_SUCCESS;
1699 
1700 error_cleanup:
1701     SAFE_FREE(*signature);
1702     return r;
1703 }
1704 
1705 /** Compute the JSON representation of quote information.
1706  *
1707  * The attest generated by a TPM quote will be converted into a
1708  * JSON representation together with the signature scheme of the
1709  * key used for the quote.
1710  *
1711  * @param[in]  sig_key_object The key object which was used for the quote.
1712  * @param[in]  tpm_quoted: The attest produced by the quote.
1713  * @param[out] quoteInfo The character string with the JSON representation of the
1714  *             attest together with the signing schemed.
1715  *
1716  * @retval TSS2_RC_SUCCESS: If the conversion was successful.
1717  * @retval TSS2_FAPI_RC_MEMORY: if not enough memory can be allocated.
1718  * @retval TSS2_FAPI_RC_BAD_VALUE: If an invalid value is detected during
1719  *         serialisation.
1720  * @retval Possible error codes of the unmarshaling function.
1721  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
1722  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1723  */
1724 TSS2_RC
ifapi_compute_quote_info(IFAPI_OBJECT * sig_key_object,TPM2B_ATTEST * tpm_quoted,char ** quoteInfo)1725 ifapi_compute_quote_info(
1726     IFAPI_OBJECT *sig_key_object,
1727     TPM2B_ATTEST *tpm_quoted,
1728     char **quoteInfo)
1729 {
1730     json_object *jso = NULL;
1731     TSS2_RC r;
1732     size_t offset = 0;
1733     TPMS_ATTEST attest_struct;
1734     FAPI_QUOTE_INFO fapi_quote_info;
1735 
1736     /* The TPM2B_ATTEST contains the marshaled TPMS_ATTEST structure. */
1737     r = Tss2_MU_TPMS_ATTEST_Unmarshal((const uint8_t *)
1738                                       &tpm_quoted->attestationData[0],
1739                                       tpm_quoted->size, &offset, &attest_struct);
1740     return_if_error(r, "Unmarshal TPMS_ATTEST.");
1741 
1742     fapi_quote_info.attest = attest_struct;
1743     /* The signate scheme will be taken from the key used for qoting. */
1744     fapi_quote_info.sig_scheme = sig_key_object->misc.key.signing_scheme;
1745     r = ifapi_json_FAPI_QUOTE_INFO_serialize(&fapi_quote_info, &jso);
1746     return_if_error(r, "Conversion to TPM2B_ATTEST to JSON.");
1747 
1748     /* The intermediate structure of type FAPI_QOTE_INFO will be serialized. */
1749     const char *quote_json = json_object_to_json_string_ext(jso,
1750                              JSON_C_TO_STRING_PRETTY);
1751     goto_if_null(quote_json, "Conversion attest to json.",
1752                  TSS2_FAPI_RC_GENERAL_FAILURE, cleanup);
1753 
1754     *quoteInfo = strdup(quote_json);
1755     goto_if_null(*quoteInfo, "Out of memory.", TSS2_FAPI_RC_MEMORY, cleanup);
1756 
1757 cleanup:
1758     json_object_put(jso);
1759     return r;
1760 }
1761 
1762 /** Deserialize the JSON representation of FAPI quote information.
1763  *
1764  * The JSON representation of FAPI quote information will be
1765  * deserialized to a FAPI_QUOTE_INFO structure and also the TPM2B
1766  * version of the attest will be created.
1767  *
1768  * @param[in]  quoteInfo The JSON representation if the quote
1769  *             information.
1770  * @param[out] tpm_quoted: The marhaled version of the attest structure.
1771  * @param[out] fapi_quote_info The quote information structure used by
1772  *             FAPI.
1773  *
1774  * @retval TSS2_RC_SUCCESS: If the deserialization was successful.
1775  * @retval TSS2_FAPI_RC_BAD_VALUE: If an invalid value is detected during
1776  *         deserialisation.
1777  * @retval Possible error codes of the marshaling function.
1778  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1779  */
1780 TSS2_RC
ifapi_get_quote_info(char const * quoteInfo,TPM2B_ATTEST * tpm_quoted,FAPI_QUOTE_INFO * fapi_quote_info)1781 ifapi_get_quote_info(
1782     char const *quoteInfo,
1783     TPM2B_ATTEST *tpm_quoted,
1784     FAPI_QUOTE_INFO *fapi_quote_info)
1785 {
1786     json_object *jso = NULL;
1787     TSS2_RC r;
1788     size_t offset = 0;
1789 
1790     jso = json_tokener_parse(quoteInfo);
1791     return_if_null(jso, "Json error.", TSS2_FAPI_RC_BAD_VALUE);
1792 
1793     memset(&fapi_quote_info->attest.attested.quote.pcrSelect, 0,
1794            sizeof(TPML_PCR_SELECTION));
1795 
1796     r = ifapi_json_FAPI_QUOTE_INFO_deserialize(jso, fapi_quote_info);
1797     goto_if_error(r, "Conversion to JSON of TPM2S_ATTEST.", cleanup);
1798 
1799     offset = 0;
1800     r = Tss2_MU_TPMS_ATTEST_Marshal(&fapi_quote_info->attest,
1801                                     (uint8_t *)&tpm_quoted->attestationData[0],
1802                                     sizeof(TPMS_ATTEST), &offset);
1803     LOGBLOB_TRACE(&tpm_quoted->attestationData[0],
1804                   offset,
1805                   "Attest");
1806     tpm_quoted-> size = offset;
1807     goto_if_error(r, "Marshal attest.", cleanup);
1808 
1809 cleanup:
1810     if (jso)
1811         json_object_put(jso);
1812     return r;
1813 }
1814 
1815 /** Determine start index for NV object depending on type.
1816  *
1817  * The value will be determined based on e TCG handle registry.
1818  *
1819  * @param[in]  path The path used for the NV object.
1820  * @param[out] start_nv_index The first possible NV index for this type.
1821  *
1822  * @retval TSS2_RC_SUCCESS If the index for the path can be determined.
1823  * @retval TSS2_FAPI_RC_BAD_PATH If no handle can be assigned.
1824  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1825  */
1826 TSS2_RC
ifapi_get_nv_start_index(const char * path,TPM2_HANDLE * start_nv_index)1827 ifapi_get_nv_start_index(const char *path, TPM2_HANDLE *start_nv_index)
1828 {
1829     NODE_STR_T *dir_list = split_string(path, IFAPI_FILE_DELIM);
1830 
1831     *start_nv_index = 0;
1832 
1833     return_if_null(dir_list, "Out of memory.", TSS2_FAPI_RC_MEMORY);
1834     if (dir_list->next && strcmp(dir_list->str, "nv") == 0) {
1835         if (strcmp(dir_list->next->str, "TPM") == 0)
1836             *start_nv_index = 0x01000000;
1837         else if (strcmp(dir_list->next->str, "Platform") == 0)
1838             *start_nv_index = 0x01400000;
1839         else if (strcmp(dir_list->next->str, "Owner") == 0)
1840             *start_nv_index = 0x01800000;
1841         else if (strcmp(dir_list->next->str, "Endorsement_Certificate") == 0)
1842             *start_nv_index = 0x01c00000;
1843         else if (strcmp(dir_list->next->str, "Platform_Certificate") == 0)
1844             *start_nv_index = 0x01c80000;
1845         else if (strcmp(dir_list->next->str, "Component_OEM") == 0)
1846             *start_nv_index = 0x01c10000;
1847         else if (strcmp(dir_list->next->str, "TPM_OEM") == 0)
1848             *start_nv_index = 0x01c20000;
1849         else if (strcmp(dir_list->next->str, "Platform_OEM") == 0)
1850             *start_nv_index = 0x01c30000;
1851         else if (strcmp(dir_list->next->str, "PC-Client") == 0)
1852             *start_nv_index = 0x01c40000;
1853         else if (strcmp(dir_list->next->str, "Sever") == 0)
1854             *start_nv_index = 0x01c50000;
1855         else if (strcmp(dir_list->next->str, "Virtualized_Platform") == 0)
1856             *start_nv_index = 0x01c60000;
1857         else if (strcmp(dir_list->next->str, "MPWG") == 0)
1858             *start_nv_index = 0x01c70000;
1859         else if (strcmp(dir_list->next->str, "Embedded") == 0)
1860             *start_nv_index = 0x01c80000;
1861     }
1862     free_string_list(dir_list);
1863     if (*start_nv_index)
1864         return TSS2_RC_SUCCESS;
1865 
1866     return_error2(TSS2_FAPI_RC_BAD_PATH, "Invalid NV path: %s", path);
1867 }
1868 
1869 /** Compute new PCR value from a part of an event list.
1870  *
1871  * @param[in,out] vpcr The old and the new PCR value.
1872  * @param[in] bank The bank corresponding to value of the event list
1873  *                 which will be used for computation.
1874  * @param[in] event The event list with the values which were extended
1875  *                  for a certain bank.
1876  * @retval TSS2_FAPI_RC_BAD_VALUE if the bank was not found in the event list.
1877  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
1878  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1879  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1880  */
1881 TSS2_RC
ifapi_extend_vpcr(TPM2B_DIGEST * vpcr,TPMI_ALG_HASH bank,const IFAPI_EVENT * event)1882 ifapi_extend_vpcr(
1883     TPM2B_DIGEST *vpcr,
1884     TPMI_ALG_HASH bank,
1885     const IFAPI_EVENT *event)
1886 {
1887     TSS2_RC r;
1888     size_t i;
1889     size_t event_size, size;
1890     IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext;
1891 
1892     LOGBLOB_TRACE(&vpcr->buffer[0], vpcr->size, "Old vpcr value");
1893 
1894     for (i = 0; i < event->digests.count; i++) {
1895         if (event->digests.digests[i].hashAlg == bank) {
1896             event_size = ifapi_hash_get_digest_size(event->digests.digests[i].hashAlg);
1897 
1898             LOGBLOB_TRACE(&event->digests.digests[i].digest.sha512[0], event_size,
1899                           "Extending with");
1900 
1901             r = ifapi_crypto_hash_start(&cryptoContext, bank);
1902             return_if_error(r, "crypto hash start");
1903 
1904             HASH_UPDATE_BUFFER(cryptoContext, &vpcr->buffer[0], vpcr->size, r, error_cleanup);
1905             HASH_UPDATE_BUFFER(cryptoContext, &event->digests.digests[i].digest.sha512[0],
1906                                event_size, r, error_cleanup);
1907             r = ifapi_crypto_hash_finish(&cryptoContext, &vpcr->buffer[0], &size);
1908             return_if_error(r, "crypto hash finish");
1909             vpcr->size = size;
1910             break;
1911         }
1912     }
1913     if (i == event->digests.count) {
1914         LOG_ERROR("No digest for bank %"PRIu16" found in event", bank);
1915         return TSS2_FAPI_RC_BAD_VALUE;
1916     }
1917     LOGBLOB_TRACE(&vpcr->buffer[0], vpcr->size, "New vpcr value");
1918 
1919     return TSS2_RC_SUCCESS;
1920 
1921 error_cleanup:
1922     ifapi_crypto_hash_abort(&cryptoContext);
1923     return r;
1924 }
1925 
1926 /** Check whether a event list corresponds to a certain quote information.
1927  *
1928  * The event list is used to compute the PCR values corresponding
1929  * to this event list. The PCR digest for these PCRs is computed and compared
1930  * with the attest passed with quote_info.
1931  *
1932  * @param[in]  jso_event_list The event list in JSON representation.
1933  * @param[in]  quote_info The information structure with the attest.
1934  * @param[out] pcr_digest The computed pcr_digest for the PCRs uses by FAPI.
1935  *
1936  * @retval TSS2_RC_SUCCESS: If the PCR digest from the event list matches
1937  *         the PCR digest passed with the quote_info.
1938  * @retval TSS2_FAPI_RC_SIGNATURE_VERIFICATION_FAILED: If the digest computed
1939  *         from event list does not match the attest
1940  * @retval TSS2_FAPI_RC_BAD_VALUE: If inappropriate values are detected in the
1941  *         input data.
1942  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
1943  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1944  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1945  */
1946 TSS2_RC
ifapi_calculate_pcr_digest(json_object * jso_event_list,const FAPI_QUOTE_INFO * quote_info,TPM2B_DIGEST * pcr_digest)1947 ifapi_calculate_pcr_digest(
1948     json_object *jso_event_list,
1949     const FAPI_QUOTE_INFO *quote_info,
1950     TPM2B_DIGEST *pcr_digest)
1951 {
1952     TSS2_RC r;
1953     IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext = NULL;
1954 
1955     struct {
1956         TPMI_ALG_HASH bank;
1957         TPM2_HANDLE pcr;
1958         TPM2B_DIGEST value;
1959     } pcrs[TPM2_MAX_PCRS];
1960     size_t i, pcr, i_evt, hash_size, n_pcrs = 0, n_events = 0;
1961 
1962     json_object *jso;
1963     IFAPI_EVENT event;
1964 
1965     const TPML_PCR_SELECTION *pcr_selection;
1966     TPMI_ALG_HASH pcr_digest_hash_alg;
1967 
1968     /* Get some data from the quote info for easier access */
1969     pcr_selection = &quote_info->attest.attested.quote.pcrSelect;
1970     pcr_digest->size = quote_info->attest.attested.quote.pcrDigest.size;
1971 
1972     switch (quote_info->sig_scheme.scheme) {
1973     case TPM2_ALG_RSAPSS:
1974         pcr_digest_hash_alg = quote_info->sig_scheme.details.rsapss.hashAlg;
1975         break;
1976     case TPM2_ALG_RSASSA:
1977         pcr_digest_hash_alg = quote_info->sig_scheme.details.rsassa.hashAlg;
1978         break;
1979     case TPM2_ALG_ECDSA:
1980         pcr_digest_hash_alg = quote_info->sig_scheme.details.ecdsa.hashAlg;
1981         break;
1982     default:
1983         LOG_ERROR("Unknown sig scheme");
1984         return TSS2_FAPI_RC_BAD_VALUE;
1985     }
1986 
1987     /* Initialize used pcrs */
1988     for (i = 0; i < pcr_selection->count; i++) {
1989         for (pcr = 0; pcr < TPM2_MAX_PCRS; pcr++) {
1990             uint8_t byte_idx = pcr / 8;
1991             uint8_t flag = 1 << (pcr % 8);
1992             if (flag & pcr_selection->pcrSelections[i].pcrSelect[byte_idx]) {
1993                 hash_size = ifapi_hash_get_digest_size(pcr_selection->pcrSelections[i].hash);
1994                 pcrs[n_pcrs].pcr = pcr;
1995                 pcrs[n_pcrs].bank = pcr_selection->pcrSelections[i].hash;
1996                 pcrs[n_pcrs].value.size = hash_size;
1997                 memset(&pcrs[n_pcrs].value.buffer[0], 0, hash_size);
1998                 n_pcrs += 1;
1999             }
2000         }
2001     }
2002 
2003     /* Compute pcr values based on event list */
2004     if (jso_event_list) {
2005         n_events = json_object_array_length(jso_event_list);
2006         for (i_evt = 0; i_evt < n_events; i_evt++) {
2007             jso = json_object_array_get_idx(jso_event_list, i_evt);
2008             r = ifapi_json_IFAPI_EVENT_deserialize(jso, &event);
2009             goto_if_error(r, "Error serialize policy", error_cleanup);
2010 
2011             for (i = 0; i < n_pcrs; i++) {
2012                  r = ifapi_extend_vpcr(&pcrs[i].value, pcrs[i].bank, &event);
2013                  goto_if_error2(r, "Extending vpcr %"PRIu32, error_cleanup, pcrs[i].pcr);
2014             }
2015         }
2016     }
2017 
2018     /* Compute digest for the used pcrs */
2019     r = ifapi_crypto_hash_start(&cryptoContext, pcr_digest_hash_alg);
2020     return_if_error(r, "crypto hash start");
2021 
2022     for (i = 0; i < n_pcrs; i++) {
2023         HASH_UPDATE_BUFFER(cryptoContext, &pcrs[i].value.buffer, pcrs[i].value.size,
2024                            r, error_cleanup);
2025     }
2026     r = ifapi_crypto_hash_finish(&cryptoContext,
2027                                  (uint8_t *) &pcr_digest->buffer[0],
2028                                  &hash_size);
2029     return_if_error(r, "crypto hash finish");
2030     pcr_digest->size = hash_size;
2031 
2032     /* Compare the digest from the event list with the digest from the attest */
2033     if (memcmp(&pcr_digest->buffer[0], &quote_info->attest.attested.quote.pcrDigest.buffer[0],
2034                pcr_digest->size) != 0) {
2035         goto_error(r, TSS2_FAPI_RC_SIGNATURE_VERIFICATION_FAILED,
2036                    "The digest computed from event list does not match the attest.",
2037                    error_cleanup);
2038     }
2039 
2040 error_cleanup:
2041     if (cryptoContext)
2042         ifapi_crypto_hash_abort(&cryptoContext);
2043     ifapi_cleanup_event(&event);
2044     return r;
2045 }
2046 
2047 /** Check whether profile PCR capabilities are a subset of TPM PCR capabilities.
2048  *
2049  * It has to be checked that every hash alg from the profile is available and
2050  * whether the selected PCRs are available.
2051  * @param[in] pcr_profile The pcr profile to use as basis for the selection.
2052  * @param[in] pcr_capablity The PCR capabilities  available for TPM.
2053  * @retval TSS2_RC_SUCCESSS if the conversion was successful.
2054  * @retval TSS2_FAPI_RC_BAD_VALUE if profile is not subset of capabilities.
2055  */
2056 TSS2_RC
ifapi_check_profile_pcr_selection(const TPML_PCR_SELECTION * pcr_profile,const TPML_PCR_SELECTION * pcr_capablity)2057 ifapi_check_profile_pcr_selection(
2058     const TPML_PCR_SELECTION *pcr_profile,
2059     const TPML_PCR_SELECTION *pcr_capablity)
2060 {
2061     size_t i, j, k;
2062 
2063     for (i = 0; i < pcr_profile->count; i++) {
2064         bool hash_found = false;
2065         for (j = 0; j < pcr_capablity->count; j++) {
2066             if (pcr_capablity->pcrSelections[j].hash ==
2067                     pcr_profile->pcrSelections[i].hash) {
2068                 /* Hash algorithm found, check PCRs */
2069                 hash_found = true;
2070                 if (pcr_profile->pcrSelections[i].sizeofSelect >
2071                         pcr_capablity->pcrSelections[j].sizeofSelect) {
2072                     return_error(TSS2_FAPI_RC_BAD_VALUE, "Invalid size of PCR select.");
2073                 }
2074 
2075                 for (k = 0;
2076                         k < pcr_profile->pcrSelections[i].sizeofSelect;
2077                         k++) {
2078                     /* Check whether all selected PCRs are available */
2079                     if ((pcr_profile->pcrSelections[i].pcrSelect[k] &
2080                             pcr_capablity->pcrSelections[j].pcrSelect[k])
2081                             != pcr_profile->pcrSelections[i].pcrSelect[k]) {
2082                         return_error(TSS2_FAPI_RC_BAD_VALUE, "Invalid PCR selection.");
2083 
2084                     }
2085                 }
2086             }
2087         }
2088         if (!hash_found) {
2089             return_error(TSS2_FAPI_RC_BAD_VALUE,
2090                          "Hash alg for PCR selection not available.");
2091         }
2092     }
2093     return TSS2_RC_SUCCESS;
2094 }
2095 
2096 /** Reduce a PCR selection to a single pcr.
2097  *
2098  * This includes two steps: clearing all bits but the selected and clearing empty hashalg lines.
2099  *
2100  * @param[in,out] pcr_selection The pcr selection to be filtered.
2101  * @param[in] pcr_index The only PCR to remain selected.
2102  * @param[in]  pcr_count The size of the pcr list.
2103  *
2104  * @retval TSS2_RC_SUCCESS if the filtering was successful.
2105  * @retval TSS2_FAPI_RC_BAD_VALUE if no pcr remain selected or the pcr selection is malformed.
2106  */
2107 TSS2_RC
ifapi_filter_pcr_selection_by_index(TPML_PCR_SELECTION * pcr_selection,const TPM2_HANDLE * pcr_index,size_t pcr_count)2108 ifapi_filter_pcr_selection_by_index(
2109     TPML_PCR_SELECTION *pcr_selection,
2110     const TPM2_HANDLE *pcr_index,
2111     size_t pcr_count)
2112 {
2113     UINT32 bank, j;
2114     UINT16 select;
2115     size_t i;
2116     UINT8 selection[] = { 0, 0, 0, 0 };
2117 
2118     for (i = 0; i < pcr_count; i++) {
2119         selection[0] |= (1 << pcr_index[i]) % 256;
2120         selection[1] |= (1 << (pcr_index[i] - 8)) % 256;
2121         selection[2] |= (1 << (pcr_index[i] - 16)) % 256;
2122         selection[3] |= (1 << (pcr_index[i] - 24)) % 256;
2123     };
2124 
2125     /* Remove unselected PCRs */
2126     for (bank = 0; bank < pcr_selection->count; bank++) {
2127         if (pcr_selection->pcrSelections[bank].sizeofSelect > 4) {
2128             LOG_ERROR("pcrSelection's sizeofSelect exceeds allowed value of 4, is %"PRIu16,
2129                       pcr_selection->pcrSelections[bank].sizeofSelect);
2130             return TSS2_FAPI_RC_BAD_VALUE;
2131         }
2132         for (select = 0; select < pcr_selection->pcrSelections[bank].sizeofSelect; select++) {
2133             pcr_selection->pcrSelections[bank].pcrSelect[select] &= selection[select];
2134         }
2135     }
2136 
2137     /* Remove empty banks */
2138     for (bank = 0; bank < pcr_selection->count; ) {
2139         for (select = 0; select < pcr_selection->pcrSelections[bank].sizeofSelect; select++) {
2140             if (pcr_selection->pcrSelections[bank].pcrSelect[select])
2141                 break;
2142         }
2143         if (select < pcr_selection->pcrSelections[bank].sizeofSelect) {
2144             /* Bank contains selections */
2145             bank ++;
2146             continue;
2147         }
2148 
2149         /* Bank contains no selections, move all other banks one up */
2150         pcr_selection->count -= 1;
2151         for (j = bank; j < pcr_selection->count; j++) {
2152             pcr_selection->pcrSelections[j] = pcr_selection->pcrSelections[j+1];
2153         }
2154     }
2155 
2156     if (pcr_selection->count == 0) {
2157         LOGBLOB_WARNING((void*)pcr_index, pcr_count * sizeof(*pcr_index),
2158                         "pcr selection is empty after filtering for pcrlist");
2159         return TSS2_FAPI_RC_BAD_VALUE;
2160     }
2161     return TSS2_RC_SUCCESS;
2162 }
2163 
2164 /** Compute PCR selection and a PCR digest for a PCR value list.
2165  *
2166  * @param[in]  pcrs The list of PCR values.
2167  * @param[out] pcr_selection The selection computed based on the
2168  *             list of PCR values.
2169  * @param[in]  hash_alg The hash algorithm which is used for the policy computation.
2170  * @param[out] pcr_digest The computed PCR digest corresponding to the passed
2171  *             PCR value list.
2172  *
2173  * @retval TSS2_RC_SUCCESS if the PCR selection and the PCR digest could be computed..
2174  * @retval TSS2_FAPI_RC_BAD_VALUE: If inappropriate values are detected in the
2175  *         input data.
2176  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
2177  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
2178  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
2179  */
2180 TSS2_RC
ifapi_compute_policy_digest(TPML_PCRVALUES * pcrs,TPML_PCR_SELECTION * pcr_selection,TPMI_ALG_HASH hash_alg,TPM2B_DIGEST * pcr_digest)2181 ifapi_compute_policy_digest(
2182     TPML_PCRVALUES *pcrs,
2183     TPML_PCR_SELECTION *pcr_selection,
2184     TPMI_ALG_HASH hash_alg,
2185     TPM2B_DIGEST *pcr_digest)
2186 {
2187     TSS2_RC r = TSS2_RC_SUCCESS;
2188     size_t i, j;
2189     IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext = NULL;
2190     size_t hash_size;
2191     UINT32 pcr;
2192     UINT32 max_pcr = 0;
2193 
2194     memset(pcr_selection, 0, sizeof(TPML_PCR_SELECTION));
2195 
2196     /* Compute PCR selection */
2197     pcr_selection->count = 0;
2198     for (i = 0; i < pcrs->count; i++) {
2199         for (j = 0; j < pcr_selection->count; j++) {
2200             if (pcrs->pcrs[i].hashAlg ==
2201                 pcr_selection->pcrSelections[j].hash) {
2202                 break;
2203             }
2204         }
2205         if (j == pcr_selection->count) {
2206             /* New hash alg */
2207             pcr_selection->count += 1;
2208             if (pcr_selection->count > TPM2_NUM_PCR_BANKS) {
2209                 return_error(TSS2_FAPI_RC_BAD_VALUE,
2210                              "More hash algs than banks.");
2211             }
2212             pcr_selection->pcrSelections[j].hash =
2213                 pcrs->pcrs[i].hashAlg;
2214         }
2215         UINT32 pcrIndex = pcrs->pcrs[i].pcr;
2216         if (pcrIndex + 1 > max_pcr)
2217             max_pcr = pcrIndex + 1;
2218         pcr_selection->pcrSelections[j].pcrSelect[pcrIndex / 8] |=
2219             1 << pcrIndex % 8;
2220         if ((pcrIndex / 8) + 1 > pcr_selection->pcrSelections[j].sizeofSelect)
2221             pcr_selection->pcrSelections[j].sizeofSelect = (pcrIndex / 8) + 1;
2222     }
2223     /* Compute digest for current pcr selection */
2224     r = ifapi_crypto_hash_start(&cryptoContext, hash_alg);
2225     return_if_error(r, "crypto hash start");
2226 
2227     if (!(pcr_digest->size = ifapi_hash_get_digest_size(hash_alg))) {
2228         goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
2229                    "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
2230                    hash_alg);
2231     }
2232 
2233     for (i = 0; i < pcr_selection->count; i++) {
2234         TPMS_PCR_SELECTION selection = pcr_selection->pcrSelections[i];
2235         TPMI_ALG_HASH hashAlg = selection.hash;
2236         if (!(hash_size = ifapi_hash_get_digest_size(hashAlg))) {
2237             goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
2238                        "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
2239                        hashAlg);
2240         }
2241         for (pcr = 0; pcr < max_pcr; pcr++) {
2242             if ((selection.pcrSelect[pcr / 8]) & (1 << (pcr % 8))) {
2243                 /* pcr selected */
2244                 for (j = 0; j < pcrs->count; j++) {
2245                     if (pcrs->pcrs[j].pcr == pcr) {
2246                         r = ifapi_crypto_hash_update(cryptoContext,
2247                                                      (const uint8_t *)&pcrs->
2248                                                      pcrs[j].digest,
2249                                                      hash_size);
2250                         goto_if_error(r, "crypto hash update", cleanup);
2251                     }
2252                 }
2253             }
2254         }
2255     }
2256     r = ifapi_crypto_hash_finish(&cryptoContext,
2257                                  (uint8_t *) & pcr_digest->buffer[0],
2258                                  &hash_size);
2259 cleanup:
2260     if (cryptoContext)
2261         ifapi_crypto_hash_abort(&cryptoContext);
2262     return r;
2263 }
2264 
2265 /** Compare two public keys.
2266  *
2267  * @param[in] key1 The first key.
2268  * @param[in] key2 The second key.
2269  * @retval true if equal false if not.
2270  */
2271 bool
ifapi_cmp_public_key(TPM2B_PUBLIC * key1,TPM2B_PUBLIC * key2)2272 ifapi_cmp_public_key(
2273     TPM2B_PUBLIC *key1,
2274     TPM2B_PUBLIC *key2)
2275 {
2276     if (key1->publicArea.type != key2->publicArea.type)
2277         return false;
2278     switch (key1->publicArea.type) {
2279     case TPM2_ALG_RSA:
2280         if (key1->publicArea.unique.rsa.size != key2->publicArea.unique.rsa.size) {
2281             return false;
2282         }
2283         LOGBLOB_TRACE(&key1->publicArea.unique.rsa.buffer[0],
2284                       key1->publicArea.unique.rsa.size, "Key 1");
2285         LOGBLOB_TRACE(&key2->publicArea.unique.rsa.buffer[0],
2286                       key2->publicArea.unique.rsa.size, "Key 2");
2287         if (memcmp(&key1->publicArea.unique.rsa.buffer[0],
2288                    &key2->publicArea.unique.rsa.buffer[0],
2289                    key1->publicArea.unique.rsa.size) == 0)
2290             return true;
2291         else
2292             return false;
2293         break;
2294     case TPM2_ALG_ECC:
2295         if (key1->publicArea.unique.ecc.x.size != key2->publicArea.unique.ecc.x.size) {
2296             return false;
2297         }
2298         LOGBLOB_TRACE(&key1->publicArea.unique.ecc.x.buffer[0],
2299                       key1->publicArea.unique.ecc.x.size, "Key 1 x");
2300         LOGBLOB_TRACE(&key2->publicArea.unique.ecc.x.buffer[0],
2301                       key2->publicArea.unique.ecc.x.size, "Key 2 x");
2302         if (memcmp(&key1->publicArea.unique.ecc.x.buffer[0],
2303                    &key2->publicArea.unique.ecc.x.buffer[0],
2304                    key1->publicArea.unique.ecc.x.size) != 0)
2305             return false;
2306         if (key1->publicArea.unique.ecc.y.size != key2->publicArea.unique.ecc.y.size) {
2307             return false;
2308         }
2309         LOGBLOB_TRACE(&key1->publicArea.unique.ecc.y.buffer[0],
2310                       key1->publicArea.unique.ecc.y.size, "Key 1 x");
2311         LOGBLOB_TRACE(&key2->publicArea.unique.ecc.y.buffer[0],
2312                       key2->publicArea.unique.ecc.y.size, "Key 2 x");
2313         if (memcmp(&key1->publicArea.unique.ecc.y.buffer[0],
2314                    &key2->publicArea.unique.ecc.y.buffer[0],
2315                    key1->publicArea.unique.ecc.y.size) != 0)
2316             return false;
2317         else
2318             return true;
2319         break;
2320 
2321     default:
2322         return false;
2323     }
2324 }
2325 
2326 struct CurlBufferStruct {
2327   unsigned char *buffer;
2328   size_t size;
2329 };
2330 
2331 /** Callback for copying received curl data to a buffer.
2332  *
2333  * The buffer will be reallocated according to the size of retrieved data.
2334  *
2335  * @param[in]  contents The retrieved content.
2336  * @param[in]  size the block size in the content.
2337  * @param[in]  nmemb The number of blocks.
2338  * @retval realsize The byte size of the data.
2339  */
2340 static size_t
write_curl_buffer_cb(void * contents,size_t size,size_t nmemb,void * userp)2341 write_curl_buffer_cb(void *contents, size_t size, size_t nmemb, void *userp)
2342 {
2343     size_t realsize = size * nmemb;
2344     struct CurlBufferStruct *curl_buf = (struct CurlBufferStruct *)userp;
2345 
2346     unsigned char *tmp_ptr = realloc(curl_buf->buffer, curl_buf->size + realsize + 1);
2347     if (tmp_ptr == NULL) {
2348         LOG_ERROR("Can't allocate memory in CURL callback.");
2349         return 0;
2350     }
2351     curl_buf->buffer = tmp_ptr;
2352     memcpy(&(curl_buf->buffer[curl_buf->size]), contents, realsize);
2353     curl_buf->size += realsize;
2354     curl_buf->buffer[curl_buf->size] = 0;
2355 
2356     return realsize;
2357 }
2358 
2359 /** Get byte buffer from file system or web via curl.
2360  *
2361  * @param[in]  url The url of the resource.
2362  * @param[out] buffer The buffer retrieved via the url.
2363  * @param[out] buffer_size The size of the retrieved object.
2364  *
2365  * @retval 0 if buffer could be retrieved.
2366  * @retval -1 if an error did occur
2367  */
2368 int
ifapi_get_curl_buffer(unsigned char * url,unsigned char ** buffer,size_t * buffer_size)2369 ifapi_get_curl_buffer(unsigned char * url, unsigned char ** buffer,
2370                           size_t *buffer_size) {
2371     int ret = -1;
2372     struct CurlBufferStruct curl_buffer = { .size = 0, .buffer = NULL };
2373 
2374     CURLcode rc = curl_global_init(CURL_GLOBAL_DEFAULT);
2375     if (rc != CURLE_OK) {
2376         LOG_ERROR("curl_global_init failed: %s", curl_easy_strerror(rc));
2377         goto out_memory;
2378     }
2379 
2380     CURL *curl = curl_easy_init();
2381     if (!curl) {
2382         LOG_ERROR("curl_easy_init failed");
2383         goto out_global_cleanup;
2384     }
2385 
2386     rc = curl_easy_setopt(curl, CURLOPT_URL, url);
2387     if (rc != CURLE_OK) {
2388         LOG_ERROR("curl_easy_setopt for CURLOPT_URL failed: %s",
2389                 curl_easy_strerror(rc));
2390         goto out_easy_cleanup;
2391     }
2392 
2393     rc = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
2394                           write_curl_buffer_cb);
2395     if (rc != CURLE_OK) {
2396         LOG_ERROR("curl_easy_setopt for CURLOPT_URL failed: %s",
2397                 curl_easy_strerror(rc));
2398         goto out_easy_cleanup;
2399     }
2400 
2401     rc = curl_easy_setopt(curl, CURLOPT_WRITEDATA,
2402                           (void *)&curl_buffer);
2403     if (rc != CURLE_OK) {
2404         LOG_ERROR("curl_easy_setopt for CURLOPT_URL failed: %s",
2405                 curl_easy_strerror(rc));
2406         goto out_easy_cleanup;
2407     }
2408 
2409     if (LOGMODULE_status == LOGLEVEL_TRACE) {
2410         if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L)) {
2411             LOG_WARNING("Curl easy setopt verbose failed");
2412         }
2413     }
2414 
2415     rc = curl_easy_perform(curl);
2416     if (rc != CURLE_OK) {
2417         LOG_ERROR("curl_easy_perform() failed: %s", curl_easy_strerror(rc));
2418         goto out_easy_cleanup;
2419     }
2420 
2421     *buffer = curl_buffer.buffer;
2422     *buffer_size = curl_buffer.size;
2423 
2424     ret = 0;
2425 
2426 out_easy_cleanup:
2427     if (ret != 0)
2428         free(curl_buffer.buffer);
2429     curl_easy_cleanup(curl);
2430 out_global_cleanup:
2431     curl_global_cleanup();
2432 out_memory:
2433     return ret;
2434 }
2435