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