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 = "e_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], "e_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