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