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
22 #include "tss2_mu.h"
23 #include "fapi_util.h"
24 #include "fapi_crypto.h"
25 #include "ifapi_helpers.h"
26 #include "ifapi_json_serialize.h"
27 #include "ifapi_json_deserialize.h"
28 #include "tpm_json_deserialize.h"
29 #include "fapi_policy.h"
30 #include "ifapi_policyutil_execute.h"
31 #define LOGMODULE fapi
32 #include "util/log.h"
33 #include "util/aux_util.h"
34
35 /** State machine for flushing objects.
36 *
37 * @param[in] context The FAPI_CONTEXT.
38 * @param[in] handle of the object to be flushed.
39 *
40 * @retval TSS2_RC_SUCCESS on success.
41 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
42 * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
43 * this function needs to be called again.
44 * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
45 * operation already pending.
46 */
47 TSS2_RC
ifapi_flush_object(FAPI_CONTEXT * context,ESYS_TR handle)48 ifapi_flush_object(FAPI_CONTEXT *context, ESYS_TR handle)
49 {
50 TSS2_RC r = TSS2_RC_SUCCESS;
51
52 if (handle == ESYS_TR_NONE)
53 return r;
54
55 switch (context->flush_object_state) {
56 statecase(context->flush_object_state, FLUSH_INIT);
57 r = Esys_FlushContext_Async(context->esys, handle);
58 return_if_error(r, "Flush Object");
59 fallthrough;
60
61 statecase(context->flush_object_state, WAIT_FOR_FLUSH);
62 r = Esys_FlushContext_Finish(context->esys);
63 if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN)
64 return TSS2_FAPI_RC_TRY_AGAIN;
65
66 return_if_error(r, "FlushContext");
67
68 context->flush_object_state = FLUSH_INIT;
69 return TSS2_RC_SUCCESS;
70
71 statecasedefault(context->flush_object_state);
72 }
73 }
74
75 /** Preparation for getting a session handle.
76 *
77 * The corresponding async call be executed and a session secret for encryption
78 * TPM2B parameters will be created.
79 *
80 * @param[in] esys The ESYS_CONTEXT.
81 * @param[in] saltkey The key which will be used for the encryption of the session
82 * secret.
83 * @param[in] profile The FAPI profile will be used to adjust the sessions symmetric
84 * parameters.
85 * @param[in] hashAlg The hash algorithm used for the session.
86 *
87 * @retval TSS2_RC_SUCCESS on success.
88 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
89 */
90 TSS2_RC
ifapi_get_session_async(ESYS_CONTEXT * esys,ESYS_TR saltkey,const IFAPI_PROFILE * profile,TPMI_ALG_HASH hashAlg)91 ifapi_get_session_async(ESYS_CONTEXT *esys, ESYS_TR saltkey, const IFAPI_PROFILE *profile,
92 TPMI_ALG_HASH hashAlg)
93 {
94 TSS2_RC r;
95
96 r = Esys_StartAuthSession_Async(esys, saltkey,
97 ESYS_TR_NONE,
98 ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
99 NULL,
100 TPM2_SE_HMAC, &profile->session_symmetric,
101 hashAlg);
102 return_if_error(r, "Creating session.");
103
104 return TSS2_RC_SUCCESS;
105 }
106
107 /** Call for getting a session handle and adjust session parameters.
108 *
109 * @param[in] esys The ESYS_CONTEXT.
110 * @param[out] session The session handle.
111 * @param[in] flags The flags to adjust the session attributes.
112 *
113 * @retval TSS2_RC_SUCCESS on success.
114 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
115 */
116 TSS2_RC
ifapi_get_session_finish(ESYS_CONTEXT * esys,ESYS_TR * session,TPMA_SESSION flags)117 ifapi_get_session_finish(ESYS_CONTEXT *esys, ESYS_TR *session,
118 TPMA_SESSION flags)
119 {
120 TSS2_RC r;
121 TPMA_SESSION sessionAttributes = 0;
122
123 /* Check whether authorization callback is defined */
124
125 r = Esys_StartAuthSession_Finish(esys, session);
126 if (r != TSS2_RC_SUCCESS)
127 return r;
128
129 sessionAttributes |= flags;
130 sessionAttributes |= TPMA_SESSION_CONTINUESESSION;
131
132 r = Esys_TRSess_SetAttributes(esys, *session, sessionAttributes,
133 0xff);
134 return_if_error(r, "Set session attributes.");
135
136 return TSS2_RC_SUCCESS;
137 }
138
139 /** Get the digest size of the policy of a FAPI object.
140 *
141 * @param[in] object The object with the correspodning policy.
142 *
143 * @retval The size of policy digest.
144 * @retval 0 if The object does not have a policy.
145 */
146 static size_t
policy_digest_size(IFAPI_OBJECT * object)147 policy_digest_size(IFAPI_OBJECT *object)
148 {
149 switch (object->objectType) {
150 case IFAPI_KEY_OBJ:
151 return object->misc.key.public.publicArea.authPolicy.size;
152 case IFAPI_NV_OBJ:
153 return object->misc.nv.public.nvPublic.authPolicy.size;
154 case IFAPI_HIERARCHY_OBJ:
155 return object->misc.hierarchy.authPolicy.size;
156 default:
157 return 0;
158 }
159 }
160
161 /** Add a object together with size as first element to a linked list.
162 *
163 * This function can e.g. used to add byte arrays together with their size
164 * to a linked list.
165 *
166 * @param[in] object The object to be added.
167 * @param[in] size The size of the object to be added.
168 * @param[in,out] object_list The linked list to be extended.
169 *
170 * @retval TSS2_RC_SUCCESS if the object was added.
171 * @retval TSS2_FAPI_RC_MEMORY If memory for the list extension cannot
172 * be allocated.
173 */
174 static TSS2_RC
push_object_with_size_to_list(void * object,size_t size,NODE_OBJECT_T ** object_list)175 push_object_with_size_to_list(void *object, size_t size, NODE_OBJECT_T **object_list)
176 {
177 TSS2_RC r;
178 r = push_object_to_list(object, object_list);
179 return_if_error(r, "Push object with size.");
180
181 (*object_list)->size = size;
182 return TSS2_RC_SUCCESS;
183 }
184
185 /** Initialize and expand the linked list representing a FAPI key path.
186 *
187 * From a passed key path the explicit key path will be determined. The
188 * profile and the hierarchy will be added if necessary and the extension
189 * is possible.
190 *
191 * @param[in] context_profile The profile used for extension of no profile is
192 * part of the path.
193 * @param[in] ipath The implicit pathname which has to be extended.
194 * @param[out] list_node1 The linked list for the passed key path without
195 * extensions.
196 * @param[out] current_list_node The current node in the list list_node1,
197 * which represent the tail not processed.
198 * @param[out] result The part of the new list which had been extended
199 * without the tail not processed.
200 *
201 * @retval TSS2_RC_SUCCESS: If the initialization was successful.
202 * @retval TSS2_FAPI_RC_BAD_VALUE If an invalid path was passed.
203 * @retval TSS2_FAPI_RC_MEMORY: if not enough memory can be allocated.
204 */
205 static TSS2_RC
init_explicit_key_path(const char * context_profile,const char * ipath,NODE_STR_T ** list_node1,NODE_STR_T ** current_list_node,NODE_STR_T ** result)206 init_explicit_key_path(
207 const char *context_profile,
208 const char *ipath,
209 NODE_STR_T **list_node1,
210 NODE_STR_T **current_list_node,
211 NODE_STR_T **result)
212 {
213 *list_node1 = split_string(ipath, IFAPI_FILE_DELIM);
214 NODE_STR_T *list_node = *list_node1;
215 char const *profile;
216 char *hierarchy;
217 TSS2_RC r = TSS2_RC_SUCCESS;
218
219 *result = NULL;
220 if (list_node == NULL) {
221 LOG_ERROR("Invalid path");
222 free_string_list(*list_node1);
223 return TSS2_FAPI_RC_BAD_VALUE;
224 }
225
226 /* Processing of the profile. */
227 if (strncmp("P_", list_node->str, 2) == 0) {
228 profile = list_node->str;
229 list_node = list_node->next;
230 } else {
231 profile = context_profile;
232 }
233 *result = init_string_list(profile);
234 if (*result == NULL) {
235 free_string_list(*list_node1);
236 LOG_ERROR("Out of memory");
237 return TSS2_FAPI_RC_MEMORY;
238 }
239 if (list_node == NULL) {
240 /* extend default hierarchy. */
241 hierarchy = "HS";
242 } else {
243 if (strcmp(list_node->str, "HS") == 0 ||
244 strcmp(list_node->str, "HE") == 0 ||
245 strcmp(list_node->str, "HP") == 0 ||
246 strcmp(list_node->str, "HN") == 0 ||
247 strcmp(list_node->str, "HP") == 0) {
248 hierarchy = list_node->str;
249 list_node = list_node->next;
250 }
251 /* Extend hierarchy. */
252 else if (strcmp(list_node->str, "EK") == 0) {
253 hierarchy = "HE";
254 } else if (list_node->next != NULL &&
255 (strcmp(list_node->str, "SRK") == 0 ||
256 strcmp(list_node->str, "SDK") == 0 ||
257 strcmp(list_node->str, "UNK") == 0 ||
258 strcmp(list_node->str, "UDK") == 0)) {
259 hierarchy = "HS";
260 } else {
261 hierarchy = "HS";
262 }
263 }
264
265 /* Extend the current result. */
266 if (!add_string_to_list(*result, hierarchy)) {
267 LOG_ERROR("Out of memory");
268 r = TSS2_FAPI_RC_MEMORY;
269 goto error;
270 }
271 if (list_node == NULL) {
272 goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Explicit path can't be determined.",
273 error);
274 }
275 if (!add_string_to_list(*result, list_node->str)) {
276 LOG_ERROR("Out of memory");
277 r = TSS2_FAPI_RC_MEMORY;
278 goto error;
279 }
280 *current_list_node = list_node->next;
281 return TSS2_RC_SUCCESS;
282
283 error:
284 free_string_list(*result);
285 *result = NULL;
286 free_string_list(*list_node1);
287 *list_node1 = NULL;
288 return r;
289 }
290
291 /** Free first object of a linked list.
292 *
293 * Note: Referenced objects of the list have to be freed before.
294 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
295 */
296 static TSS2_RC
pop_object_from_list(FAPI_CONTEXT * context,NODE_OBJECT_T ** object_list)297 pop_object_from_list(FAPI_CONTEXT *context, NODE_OBJECT_T **object_list)
298 {
299 return_if_null(*object_list, "Pop from list.", TSS2_FAPI_RC_BAD_REFERENCE);
300
301 NODE_OBJECT_T *head = *object_list;
302 NODE_OBJECT_T *next = head->next;
303 *object_list = next;
304 ifapi_free_object(context, (void *)&head->object);
305 free(head);
306 return TSS2_RC_SUCCESS;
307 }
308
309 /** Set authorization value for a FAPI object.
310 *
311 * The callback which provides the auth value must be defined.
312 *
313 * @param[in,out] context The FAPI_CONTEXT.
314 * @param[in] auth_object The auth value will be assigned to this object.
315 * @param[in] description The description will be passed to the callback
316 * which delivers the auth value.
317 *
318 * @retval TSS2_RC_SUCCESS on success.
319 * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN If the callback for getting
320 * the auth value is not defined.
321 */
322 TSS2_RC
ifapi_set_auth(FAPI_CONTEXT * context,IFAPI_OBJECT * auth_object,const char * description)323 ifapi_set_auth(
324 FAPI_CONTEXT *context,
325 IFAPI_OBJECT *auth_object,
326 const char *description)
327 {
328 TSS2_RC r;
329 char *auth = NULL;
330 TPM2B_AUTH authValue = {.size = 0,.buffer = {0} };
331 char *obj_description;
332
333 obj_description = get_description(auth_object);
334
335 if (obj_description)
336 description = obj_description;
337
338 /* Check whether callback is defined. */
339 if (context->callbacks.auth) {
340 r = context->callbacks.auth(context, description, &auth,
341 context->callbacks.authData);
342 return_if_error(r, "policyAuthCallback");
343 if (auth != NULL) {
344 authValue.size = strlen(auth);
345 memcpy(&authValue.buffer[0], auth, authValue.size);
346 }
347 SAFE_FREE(auth);
348 /* Store auth value in the ESYS object. */
349 r = Esys_TR_SetAuth(context->esys, auth_object->handle, &authValue);
350 return_if_error(r, "Set auth value.");
351
352 return TSS2_RC_SUCCESS;
353 }
354 SAFE_FREE(auth);
355 return TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN;
356 }
357
358 /** Preparation for getting a free handle after a start handle number.
359 *
360 * @param[in] fctx The FAPI_CONTEXT.
361 * @param[in] handle The start value for handle search.
362 *
363 * @retval TSS2_RC_SUCCESS on success.
364 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
365 */
366 TSS2_RC
ifapi_get_free_handle_async(FAPI_CONTEXT * fctx,TPM2_HANDLE * handle)367 ifapi_get_free_handle_async(FAPI_CONTEXT *fctx, TPM2_HANDLE *handle)
368 {
369 TSS2_RC r = Esys_GetCapability_Async(fctx->esys,
370 ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
371 TPM2_CAP_HANDLES, *handle, 1);
372 return_if_error(r, "GetCapability");
373 return r;
374 }
375
376 /** Execution of get capability until a free handle is found.
377 *
378 * The get capability method is called until a free handle is found
379 * or the max number of trials passe to the function is exeeded.
380 *
381 * @param[in] fctx The FAPI_CONTEXT.
382 * @param[out] handle The free handle.
383 * @param[in] max The maximal number of trials.
384 *
385 * @retval TSS2_RC_SUCCESS on success.
386 * @retval TSS2_FAPI_RC_NV_TOO_SMALL if too many NV handles are defined.
387 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
388 * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
389 * this function needs to be called again.
390 */
391 TSS2_RC
ifapi_get_free_handle_finish(FAPI_CONTEXT * fctx,TPM2_HANDLE * handle,TPM2_HANDLE max)392 ifapi_get_free_handle_finish(FAPI_CONTEXT *fctx, TPM2_HANDLE *handle,
393 TPM2_HANDLE max)
394 {
395 TPMI_YES_NO moreData;
396 TPMS_CAPABILITY_DATA *capabilityData = NULL;
397 TSS2_RC r = Esys_GetCapability_Finish(fctx->esys,
398 &moreData, &capabilityData);
399
400 if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN)
401 return TSS2_FAPI_RC_TRY_AGAIN;
402
403 return_if_error(r, "GetCapability");
404
405 if (capabilityData->data.handles.count == 0 ||
406 capabilityData->data.handles.handle[0] != *handle) {
407 SAFE_FREE(capabilityData);
408 return TSS2_RC_SUCCESS;
409 }
410 SAFE_FREE(capabilityData);
411 *handle += 1;
412 if (*handle > max) {
413 return_error(TSS2_FAPI_RC_NV_TOO_SMALL, "No NV index free.");
414 }
415
416 r = ifapi_get_free_handle_async(fctx, handle);
417 return_if_error(r, "GetCapability");
418
419 return TSS2_FAPI_RC_TRY_AGAIN;
420 }
421
422 /** Create a linked list of directories in the key store.
423 *
424 * If the absolute path in key store is not defined the list will
425 * be extended if possible.
426 *
427 * @param[out] keystore The used keystore.
428 * @param[in] ipath The implicit pathname, which might be extended.
429 * @param[out] The linked list of directories in the explicit pathname.
430 *
431 * @retval TSS2_RC_SUCCESS If the keystore can be initialized.
432 * @retval TSS2_FAPI_RC_IO_ERROR If the user part of the keystore can't be
433 * initialized.
434 * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated.
435 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
436 * the function.
437 */
438 static TSS2_RC
get_explicit_key_path(IFAPI_KEYSTORE * keystore,const char * ipath,NODE_STR_T ** result)439 get_explicit_key_path(
440 IFAPI_KEYSTORE *keystore,
441 const char *ipath,
442 NODE_STR_T **result)
443 {
444 NODE_STR_T *list_node1 = NULL;
445 NODE_STR_T *list_node = NULL;
446
447 /* Extend the first part of the list if necessary. */
448 TSS2_RC r = init_explicit_key_path(keystore->defaultprofile, ipath,
449 &list_node1, &list_node, result);
450 goto_if_error(r, "init_explicit_key_path", error);
451
452 /* Extend the list with the tail of the initial unmodified list. */
453 while (list_node != NULL) {
454 if (!add_string_to_list(*result, list_node->str)) {
455 LOG_ERROR("Out of memory");
456 r = TSS2_FAPI_RC_MEMORY;
457 goto error;
458 }
459 list_node = list_node->next;
460 }
461 free_string_list(list_node1);
462 return TSS2_RC_SUCCESS;
463
464 error:
465 if (*result)
466 free_string_list(*result);
467 if (list_node1)
468 free_string_list(list_node1);
469 return r;
470 }
471
472 /** Prepare the creation of a primary key.
473 *
474 * Depending on the parameters the creation of an endorsement or storage root key
475 * will be prepared.
476 *
477 * @param[in] context The FAPI_CONTEXT.
478 * @param[in] ktype The type of key TSS2_EK or TSS2_SRK.
479 * @retval TSS2_RC_SUCCESS on success.
480 * @retval TSS2_FAPI_RC_BAD_VALUE if a wrong type was passed.
481 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
482 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
483 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
484 * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
485 * this function needs to be called again.
486 * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
487 * operation already pending.
488 * @retval TSS2_FAPI_RC_IO_ERROR if an error occurred while accessing the
489 * object store.
490 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
491 * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found
492 * during authorization.
493 * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
494 */
495 TSS2_RC
ifapi_init_primary_async(FAPI_CONTEXT * context,TSS2_KEY_TYPE ktype)496 ifapi_init_primary_async(FAPI_CONTEXT *context, TSS2_KEY_TYPE ktype)
497 {
498 TSS2_RC r;
499 IFAPI_OBJECT *hierarchy;
500 hierarchy = &context->cmd.Provision.hierarchy;
501 TPMS_POLICY *policy;
502
503 if (ktype == TSS2_EK) {
504 /* Values set according to EK credential profile. */
505 if (context->cmd.Provision.public_templ.public.publicArea.type == TPM2_ALG_RSA) {
506 context->cmd.Provision.public_templ.public.publicArea.unique.rsa.size = 256;
507 } else if (context->cmd.Provision.public_templ.public.publicArea.type == TPM2_ALG_ECC) {
508 context->cmd.Provision.public_templ.public.publicArea.unique.ecc.x.size = 32;
509 context->cmd.Provision.public_templ.public.publicArea.unique.ecc.y.size = 32;
510 }
511 ifapi_init_hierarchy_object(hierarchy, ESYS_TR_RH_ENDORSEMENT);
512 policy = context->profiles.default_profile.ek_policy;
513 } else if (ktype == TSS2_SRK) {
514 policy = context->profiles.default_profile.srk_policy;
515 ifapi_init_hierarchy_object(hierarchy, ESYS_TR_RH_OWNER);
516 } else {
517 return_error(TSS2_FAPI_RC_BAD_VALUE,
518 "Invalid key type. Only EK or SRK allowed");
519 }
520
521 if (policy) {
522 /* Duplicate policy to prevent profile policy from cleanup. */
523 policy = ifapi_copy_policy(policy);
524 return_if_null(policy, "Out of memory.", TSS2_FAPI_RC_MEMORY);
525
526 r = ifapi_calculate_tree(context, NULL, /**< no path needed */
527 policy,
528 context->profiles.default_profile.nameAlg,
529 &context->cmd.Provision.digest_idx,
530 &context->cmd.Provision.hash_size);
531 if (r) {
532 LOG_ERROR("Policy calculation");
533 free(policy);
534 return r;
535 }
536
537 context->cmd.Provision.public_templ.public.publicArea.authPolicy.size =
538 context->cmd.Provision.hash_size;
539 memcpy(&context->cmd.Provision.public_templ.public.publicArea.authPolicy.buffer[0],
540 &policy->policyDigests.digests[context->policy.digest_idx].digest,
541 context->cmd.Provision.hash_size);
542 }
543 context->createPrimary.pkey_object.policy = policy;
544
545 memset(&context->cmd.Provision.inSensitive, 0, sizeof(TPM2B_SENSITIVE_CREATE));
546 memset(&context->cmd.Provision.outsideInfo, 0, sizeof(TPM2B_DATA));
547 memset(&context->cmd.Provision.creationPCR, 0, sizeof(TPML_PCR_SELECTION));
548
549 r = Esys_CreatePrimary_Async(context->esys, hierarchy->handle,
550 ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
551 &context->cmd.Provision.inSensitive,
552 &context->cmd.Provision.public_templ.public,
553 &context->cmd.Provision.outsideInfo,
554 &context->cmd.Provision.creationPCR);
555 return r;
556 }
557
558 /** Finalize the creation of a primary key.
559 *
560 * Depending on the parameters the creation of an endorsement key or a storage root key
561 * will be finalized. The created object with the all information needed by FAPI will
562 * be stored in the FAPI context.
563 *
564 * @param[in] context The FAPI_CONTEXT.
565 * @param[in] ktype The type of key TSS2_EK or TSS2_SRK.
566 *
567 * @retval TSS2_RC_SUCCESS on success.
568 * @retval TSS2_FAPI_RC_TRY_AGAIN if the execution cannot be completed.
569 * @retval TSS2_FAPI_RC_BAD_VALUE if a wrong type was passed.
570 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
571 * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback
572 * is not set.
573 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
574 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
575 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
576 */
577 TSS2_RC
ifapi_init_primary_finish(FAPI_CONTEXT * context,TSS2_KEY_TYPE ktype)578 ifapi_init_primary_finish(FAPI_CONTEXT *context, TSS2_KEY_TYPE ktype)
579 {
580 TSS2_RC r;
581 ESYS_TR primaryHandle;
582 IFAPI_OBJECT *hierarchy;
583 TPM2B_PUBLIC *outPublic = NULL;
584 TPM2B_CREATION_DATA *creationData = NULL;
585 TPM2B_DIGEST *creationHash = NULL;
586 TPMT_TK_CREATION *creationTicket = NULL;
587 IFAPI_KEY *pkey = &context->createPrimary.pkey_object.misc.key;
588 NODE_STR_T *k_sub_path = NULL;
589
590 hierarchy = &context->cmd.Provision.hierarchy;
591
592 r = Esys_CreatePrimary_Finish(context->esys,
593 &primaryHandle, &outPublic, &creationData, &creationHash,
594 &creationTicket);
595 if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN)
596 return TSS2_FAPI_RC_TRY_AGAIN;
597
598 /* Retry with authorization callback after trial with null auth */
599 if ((((r & ~TPM2_RC_N_MASK) == TPM2_RC_BAD_AUTH))
600 && (context->state == PROVISION_AUTH_EK_NO_AUTH_SENT ||
601 context->state == PROVISION_AUTH_SRK_NO_AUTH_SENT)) {
602 r = ifapi_set_auth(context, hierarchy, "CreatePrimary");
603 goto_if_error_reset_state(r, "CreatePrimary", error_cleanup);
604
605 r = Esys_CreatePrimary_Async(context->esys, hierarchy->handle,
606 ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
607 &context->cmd.Provision.inSensitive,
608 &context->cmd.Provision.public,
609 &context->cmd.Provision.outsideInfo,
610 &context->cmd.Provision.creationPCR);
611 goto_if_error_reset_state(r, "CreatePrimary", error_cleanup);
612
613 if (ktype == TSS2_EK)
614 context->state = PROVISION_AUTH_EK_AUTH_SENT;
615 else
616 context->state = PROVISION_AUTH_SRK_AUTH_SENT;
617 return TSS2_FAPI_RC_TRY_AGAIN;
618
619 } else {
620 goto_if_error_reset_state(r, "FAPI Provision", error_cleanup);
621 }
622 /* Set EK or SRK handle in context. */
623 if (ktype == TSS2_EK) {
624 context->ek_handle = primaryHandle;
625 } else if (ktype == TSS2_SRK) {
626 context->srk_handle = primaryHandle;
627 } else {
628 return_error(TSS2_FAPI_RC_BAD_VALUE,
629 "Invalid key type. Only EK or SRK allowed");
630 }
631
632 /* Prepare serialization of pkey to key store. */
633
634 SAFE_FREE(pkey->serialization.buffer);
635 r = Esys_TR_Serialize(context->esys, primaryHandle, &pkey->serialization.buffer,
636 &pkey->serialization.size);
637 goto_if_error(r, "Error serialize esys object", error_cleanup);
638
639 r = ifapi_get_name(&outPublic->publicArea, &pkey->name);
640 goto_if_error(r, "Get primary name", error_cleanup);
641
642 pkey->public = *outPublic;
643 pkey->policyInstance = NULL;
644 pkey->creationData = *creationData;
645 pkey->creationTicket = *creationTicket;
646 pkey->description = NULL;
647 pkey->certificate = NULL;
648
649 /* Cleanup unused information */
650 SAFE_FREE(outPublic);
651 SAFE_FREE(creationData);
652 SAFE_FREE(creationHash);
653 SAFE_FREE(creationTicket);
654
655 if (pkey->public.publicArea.type == TPM2_ALG_RSA)
656 pkey->signing_scheme = context->profiles.default_profile.rsa_signing_scheme;
657 else
658 pkey->signing_scheme = context->profiles.default_profile.ecc_signing_scheme;
659 context->createPrimary.pkey_object.handle = primaryHandle;
660 SAFE_FREE(pkey->serialization.buffer);
661 ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
662 return TSS2_RC_SUCCESS;
663
664 error_cleanup:
665 free_string_list(k_sub_path);
666 SAFE_FREE(pkey->serialization.buffer);
667 ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
668 return r;
669 }
670
671 /** Prepare the loading of a primary key from key store.
672 *
673 * The asynchronous loading or the key from keystore will be prepared and
674 * the path will be stored in the FAPI context.
675 *
676 * @param[in] context The FAPI_CONTEXT.
677 * @param[in] path The FAPI path of the primary key.
678 *
679 * @retval TSS2_RC_SUCCESS on success.
680 * @retval TSS2_FAPI_RC_BAD_VALUE if a wrong type was passed.
681 * @retval TSS2_FAPI_RC_IO_ERROR if an I/O error was encountered.
682 * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if the file does not exist.
683 * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated for path names.
684 * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
685 */
686 TSS2_RC
ifapi_load_primary_async(FAPI_CONTEXT * context,char * path)687 ifapi_load_primary_async(FAPI_CONTEXT *context, char *path)
688 {
689
690 TSS2_RC r;
691
692 memset(&context->createPrimary.pkey_object, 0, sizeof(IFAPI_OBJECT));
693 context->createPrimary.path = path;
694 r = ifapi_keystore_load_async(&context->keystore, &context->io, path);
695 return_if_error2(r, "Could not open: %s", path);
696 context->primary_state = PRIMARY_READ_KEY;
697 return TSS2_RC_SUCCESS;
698
699 }
700
701 /** State machine to finalize the loading of a primary key from key store.
702 *
703 * The asynchronous loading or the key from keystore will be finalized.
704 * Afterwards the hierarchy object, which will be used for authorization will
705 * be loaded and the ESAPI functions for primary generation will be called
706 * if the primary is not persistent.
707 *
708 * @param[in] context The FAPI_CONTEXT.
709 * @param[out] handle The object handle of the primary key.
710 *
711 * @retval TSS2_RC_SUCCESS on success.
712 * @retval TSS2_FAPI_RC_BAD_VALUE if a wrong type was passed.
713 * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if the hierarchy file does not exist.
714 * @retval TSS2_FAPI_RC_IO_ERROR if an I/O error was encountered.
715 * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated for path names.
716 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
717 * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
718 * this function needs to be called again.
719 * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
720 * operation already pending.
721 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
722 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
723 * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
724 * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback
725 * is not set.
726 * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
727 * @retval TSS2_FAPI_RC_POLICY_UNKNOWN if policy search for a certain policy digest
728 * was not successful.
729 */
730 TSS2_RC
ifapi_load_primary_finish(FAPI_CONTEXT * context,ESYS_TR * handle)731 ifapi_load_primary_finish(FAPI_CONTEXT *context, ESYS_TR *handle)
732 {
733 TSS2_RC r;
734 IFAPI_OBJECT *hierarchy = &context->createPrimary.hierarchy;
735
736 TPM2B_PUBLIC *outPublic = NULL;
737 TPM2B_CREATION_DATA *creationData = NULL;
738 TPM2B_DIGEST *creationHash = NULL;
739 TPMT_TK_CREATION *creationTicket = NULL;
740 IFAPI_OBJECT *pkey_object = &context->createPrimary.pkey_object;
741 IFAPI_KEY *pkey = &context->createPrimary.pkey_object.misc.key;
742 ESYS_TR auth_session;
743
744 LOG_TRACE("call");
745
746 switch (context->primary_state) {
747 statecase(context->primary_state, PRIMARY_READ_KEY);
748 /* Read the primary key from keystore. */
749 r = ifapi_keystore_load_finish(&context->keystore, &context->io,
750 pkey_object);
751 return_try_again(r);
752 return_if_error(r, "read_finish failed");
753
754 r = ifapi_initialize_object(context->esys, pkey_object);
755 goto_if_error_reset_state(r, "Initialize key object", error_cleanup);
756
757 /* Check whether a persistent key was loaded.
758 In this case the handle has already been set. */
759 if (pkey_object->handle != ESYS_TR_NONE) {
760 if (pkey->creationTicket.hierarchy == TPM2_RH_EK) {
761 context->ek_persistent = true;
762 } else {
763 context->srk_persistent = true;
764 }
765 /* Persistent handle will be used. */
766 *handle = pkey_object->handle;
767 break;
768 } else {
769 if (pkey->creationTicket.hierarchy == TPM2_RH_EK) {
770 context->ek_persistent = false;
771 } else {
772 context->srk_persistent = false;
773 }
774 }
775 fallthrough;
776
777 statecase(context->primary_state, PRIMARY_READ_HIERARCHY);
778 /* The hierarchy object ussed for auth_session will be loaded from key store. */
779 if (pkey->creationTicket.hierarchy == TPM2_RH_EK) {
780 r = ifapi_keystore_load_async(&context->keystore, &context->io, "/HE");
781 return_if_error2(r, "Could not open hierarchy /HE");
782 } else {
783 r = ifapi_keystore_load_async(&context->keystore, &context->io, "/HS");
784 return_if_error2(r, "Could not open hierarchy /HS");
785 }
786 fallthrough;
787
788 statecase(context->primary_state, PRIMARY_READ_HIERARCHY_FINISH);
789 r = ifapi_keystore_load_finish(&context->keystore, &context->io, hierarchy);
790 return_try_again(r);
791 return_if_error(r, "read_finish failed");
792
793 r = ifapi_initialize_object(context->esys, hierarchy);
794 goto_if_error_reset_state(r, "Initialize hierarchy object", error_cleanup);
795
796 if (pkey->creationTicket.hierarchy == TPM2_RH_EK) {
797 hierarchy->handle = ESYS_TR_RH_ENDORSEMENT;
798 } else {
799 hierarchy->handle = ESYS_TR_RH_OWNER;
800 }
801 fallthrough;
802
803 statecase(context->primary_state, PRIMARY_AUTHORIZE_HIERARCHY);
804 /* The asynchronous authorization of the hierarchy needed for primary. */
805 r = ifapi_authorize_object(context, hierarchy, &auth_session);
806 FAPI_SYNC(r, "Authorize hierarchy.", error_cleanup);
807
808 memset(&context->createPrimary.inSensitive, 0, sizeof(TPM2B_SENSITIVE_CREATE));
809 memset(&context->createPrimary.outsideInfo, 0, sizeof(TPM2B_DATA));
810 memset(&context->createPrimary.creationPCR, 0, sizeof(TPML_PCR_SELECTION));
811
812 /* Prepare primary creation. */
813 r = Esys_CreatePrimary_Async(context->esys, hierarchy->handle,
814 auth_session, ESYS_TR_NONE, ESYS_TR_NONE,
815 &context->createPrimary.inSensitive,
816 &pkey->public,
817 &context->createPrimary.outsideInfo,
818 &context->createPrimary.creationPCR);
819 return_if_error(r, "CreatePrimary");
820 fallthrough;
821
822 statecase(context->primary_state, PRIMARY_HAUTH_SENT);
823 if (context->createPrimary.handle) {
824 *handle = context->createPrimary.handle;
825 context->primary_state = PRIMARY_CREATED;
826 return TSS2_FAPI_RC_TRY_AGAIN;
827 } else {
828 r = Esys_CreatePrimary_Finish(context->esys,
829 &pkey_object->handle, &outPublic,
830 &creationData, &creationHash,
831 &creationTicket);
832 return_try_again(r);
833 goto_if_error_reset_state(r, "FAPI regenerate primary", error_cleanup);
834 }
835 *handle = pkey_object->handle;
836 context->primary_state = PRIMARY_INIT;
837 break;
838
839 statecasedefault(context->primary_state);
840 }
841 SAFE_FREE(outPublic);
842 SAFE_FREE(creationData);
843 SAFE_FREE(creationHash);
844 SAFE_FREE(creationTicket);
845 ifapi_cleanup_ifapi_object(&context->createPrimary.hierarchy);
846 return TSS2_RC_SUCCESS;
847
848 error_cleanup:
849 SAFE_FREE(outPublic);
850 SAFE_FREE(creationData);
851 SAFE_FREE(creationHash);
852 SAFE_FREE(creationTicket);
853 ifapi_cleanup_ifapi_object(&context->createPrimary.hierarchy);
854 ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
855 return r;
856 }
857
858 /** Prepare session for FAPI command execution.
859 *
860 * It will be checked whether the context of FAPI and ESAPI is initialized
861 * and whether no other FAPI command session is running.
862 * Also some handle variables in the context are initialized.
863 *
864 * @param[in] context The FAPI_CONTEXT.
865 *
866 * @retval TSS2_RC_SUCCESS on success.
867 * @retval TSS2_FAPI_RC_BAD_REFERENCE if the context is not initialized.
868 * @retval TSS2_FAPI_RC_BAD_SEQUENCE If a FAPI command session is active.
869 * @retval TSS2_FAPI_RC_NO_TPM if the ESAPI context is not initialized.
870 */
871 TSS2_RC
ifapi_session_init(FAPI_CONTEXT * context)872 ifapi_session_init(FAPI_CONTEXT *context)
873 {
874 LOG_TRACE("call");
875 return_if_null(context, "No context", TSS2_FAPI_RC_BAD_REFERENCE);
876
877 return_if_null(context->esys, "No context", TSS2_FAPI_RC_NO_TPM);
878
879 if (context->state != _FAPI_STATE_INIT) {
880 return_error(TSS2_FAPI_RC_BAD_SEQUENCE, "Invalid State");
881 }
882
883 context->session1 = ESYS_TR_NONE;
884 context->session2 = ESYS_TR_NONE;
885 context->policy.session = ESYS_TR_NONE;
886 context->srk_handle = ESYS_TR_NONE;
887 return TSS2_RC_SUCCESS;
888 }
889
890 /** Prepare session for FAPI command execution without TPM.
891 *
892 * It will be checked whether the context of FAPI is initialized
893 * and whether no other FAPI command session is running.
894 * Also some handle variables in the context are initialized.
895 *
896 * @param[in] context The FAPI_CONTEXT.
897 *
898 * @retval TSS2_RC_SUCCESS on success.
899 * @retval TSS2_FAPI_RC_BAD_REFERENCE if the context is not initialized.
900 * @retval TSS2_FAPI_RC_BAD_SEQUENCE If a FAPI command session is active.
901 */
902 TSS2_RC
ifapi_non_tpm_mode_init(FAPI_CONTEXT * context)903 ifapi_non_tpm_mode_init(FAPI_CONTEXT *context)
904 {
905 LOG_TRACE("call");
906 return_if_null(context, "No context", TSS2_FAPI_RC_BAD_REFERENCE);
907
908 if (context->state != _FAPI_STATE_INIT) {
909 return_error(TSS2_FAPI_RC_BAD_SEQUENCE, "Invalid State");
910 }
911
912 context->session1 = ESYS_TR_NONE;
913 context->session2 = ESYS_TR_NONE;
914 context->policy.session = ESYS_TR_NONE;
915 context->srk_handle = ESYS_TR_NONE;
916 return TSS2_RC_SUCCESS;
917 }
918
919 /** Cleanup FAPI sessions in error cases.
920 *
921 * The uses sessions and the SRK (if not persistent) will be flushed
922 * non asynchronous in error cases.
923 *
924 * @param[in,out] context The FAPI_CONTEXT.
925 */
926 void
ifapi_session_clean(FAPI_CONTEXT * context)927 ifapi_session_clean(FAPI_CONTEXT *context)
928 {
929 if (context->session1 != ESYS_TR_NONE) {
930 if (Esys_FlushContext(context->esys, context->session1) != TSS2_RC_SUCCESS) {
931 LOG_ERROR("Cleanup session failed.");
932 }
933 context->session1 = ESYS_TR_NONE;
934 }
935 if (context->session2 != ESYS_TR_NONE) {
936 if (Esys_FlushContext(context->esys, context->session2) != TSS2_RC_SUCCESS) {
937 LOG_ERROR("Cleanup session failed.");
938 context->session2 = ESYS_TR_NONE;
939 }
940 }
941 if (!context->srk_persistent && context->srk_handle != ESYS_TR_NONE) {
942 if (Esys_FlushContext(context->esys, context->srk_handle) != TSS2_RC_SUCCESS) {
943 LOG_ERROR("Cleanup Policy Session failed.");
944 }
945 context->srk_handle = ESYS_TR_NONE;
946 }
947 context->srk_persistent = false;
948 }
949
950 /** State machine for asynchronous cleanup of a FAPI session.
951 *
952 * Used sessions and the SRK will be flushed.
953 *
954 * @param[in] context The FAPI_CONTEXT storing the used handles.
955 *
956 * @retval TSS2_RC_SUCCESS on success.
957 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
958 * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
959 * this function needs to be called again.
960 * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
961 * operation already pending.
962 */
963 TSS2_RC
ifapi_cleanup_session(FAPI_CONTEXT * context)964 ifapi_cleanup_session(FAPI_CONTEXT *context)
965 {
966 TSS2_RC r;
967
968 switch (context->cleanup_state) {
969 statecase(context->cleanup_state, CLEANUP_INIT);
970 if (context->session1 != ESYS_TR_NONE) {
971 r = Esys_FlushContext_Async(context->esys, context->session1);
972 try_again_or_error(r, "Flush session.");
973 }
974 fallthrough;
975
976 statecase(context->cleanup_state, CLEANUP_SESSION1);
977 if (context->session1 != ESYS_TR_NONE) {
978 r = Esys_FlushContext_Finish(context->esys);
979 try_again_or_error(r, "Flush session.");
980 }
981 context->session1 = ESYS_TR_NONE;
982
983 if (context->session2 != ESYS_TR_NONE) {
984 r = Esys_FlushContext_Async(context->esys, context->session2);
985 try_again_or_error(r, "Flush session.");
986 }
987 fallthrough;
988
989 statecase(context->cleanup_state, CLEANUP_SESSION2);
990 if (context->session2 != ESYS_TR_NONE) {
991 r = Esys_FlushContext_Finish(context->esys);
992 try_again_or_error(r, "Flush session.");
993 }
994 context->session2 = ESYS_TR_NONE;
995
996 if (!context->srk_persistent && context->srk_handle != ESYS_TR_NONE) {
997 r = Esys_FlushContext_Async(context->esys, context->srk_handle);
998 try_again_or_error(r, "Flush SRK.");
999 }
1000 fallthrough;
1001
1002 statecase(context->cleanup_state, CLEANUP_SRK);
1003 if (!context->srk_persistent && context->srk_handle != ESYS_TR_NONE) {
1004 r = Esys_FlushContext_Finish(context->esys);
1005 try_again_or_error(r, "Flush SRK.");
1006
1007 context->srk_handle = ESYS_TR_NONE;
1008 context->srk_persistent = false;
1009 }
1010 context->cleanup_state = CLEANUP_INIT;
1011 return TSS2_RC_SUCCESS;
1012
1013 statecasedefault(context->state);
1014 }
1015 }
1016
1017 /** Cleanup primary keys in error cases (non asynchronous).
1018 *
1019 * @param[in] context The FAPI_CONTEXT storing the used handles.
1020 *
1021 * @retval TSS2_RC_SUCCESS on success.
1022 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
1023 */
1024 void
ifapi_primary_clean(FAPI_CONTEXT * context)1025 ifapi_primary_clean(FAPI_CONTEXT *context)
1026 {
1027 if (!context->srk_persistent && context->srk_handle != ESYS_TR_NONE) {
1028 if (Esys_FlushContext(context->esys, context->srk_handle) != TSS2_RC_SUCCESS) {
1029 LOG_ERROR("Cleanup session failed.");
1030 }
1031 context->srk_handle = ESYS_TR_NONE;
1032 }
1033 if (!context->ek_persistent && context->ek_handle != ESYS_TR_NONE) {
1034 if (Esys_FlushContext(context->esys, context->ek_handle) != TSS2_RC_SUCCESS) {
1035 LOG_ERROR("Cleanup EK failed.");
1036 }
1037 context->ek_handle = ESYS_TR_NONE;
1038 }
1039 context->srk_persistent = false;
1040 }
1041
1042 /** Prepare the session creation of a FAPI command.
1043 *
1044 * The initial state of the state machine for session creation will be determined.
1045 * Depending of the session_flags creation of a primary for the encryption of
1046 * the session secret can be adjusted.
1047 * The session passed session attributes will be used for the ESAPI command
1048 * Esys_TRSess_SetAttributes.
1049 *
1050 * @param[in] context The FAPI_CONTEXT storing the used handles.
1051 * @param[in] session_flags The flags to adjust used session and encryption
1052 * key. With IFAPI_SESSION1 and IFAPI_SESSION2 the session creation
1053 * for sesion1 and session2 can be activated, IFAPI_SESSION_GENEK
1054 * triggers the creation of the primary for session secret encryption.
1055 * @param[in] attribute_flags1 The attributes used for session1.
1056 * @param[in] attribute_flags2 The attributes used for session2.
1057 *
1058 * @retval TSS2_RC_SUCCESS on success.
1059 * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if the hierarchy file or the primary key file
1060 * does not exist.
1061 * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated for path names.
1062 * of the primary.
1063 * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
1064 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
1065 * the function.
1066 * @retval TSS2_FAPI_RC_IO_ERROR if an error occurred while accessing the
1067 * object store.
1068 */
1069 TSS2_RC
ifapi_get_sessions_async(FAPI_CONTEXT * context,IFAPI_SESSION_TYPE session_flags,TPMA_SESSION attribute_flags1,TPMA_SESSION attribute_flags2)1070 ifapi_get_sessions_async(FAPI_CONTEXT *context,
1071 IFAPI_SESSION_TYPE session_flags,
1072 TPMA_SESSION attribute_flags1,
1073 TPMA_SESSION attribute_flags2)
1074 {
1075 TSS2_RC r;
1076
1077 LOG_TRACE("call");
1078 context->session_flags = session_flags;
1079 context->session1_attribute_flags = attribute_flags1;
1080 context->session2_attribute_flags = attribute_flags2;
1081 char *file = NULL;
1082
1083 if (!(session_flags & IFAPI_SESSION_GENEK)) {
1084 context->srk_handle = ESYS_TR_NONE;
1085 context->session_state = SESSION_CREATE_SESSION;
1086 return TSS2_RC_SUCCESS;
1087 }
1088
1089 context->primary_state = PRIMARY_INIT;
1090 r = ifapi_asprintf(&file, "%s/%s", context->config.profile_name,
1091 IFAPI_SRK_KEY_PATH);
1092 goto_if_error(r, "Error ifapi_asprintf", error_cleanup);
1093
1094 r = ifapi_load_primary_async(context, file);
1095 return_if_error_reset_state(r, "Load EK");
1096 free(file);
1097
1098 context->session_state = SESSION_WAIT_FOR_PRIMARY;
1099 return TSS2_RC_SUCCESS;
1100
1101 error_cleanup:
1102 SAFE_FREE(file);
1103 return r;
1104 }
1105
1106 /** State machine for the session creation of a FAPI command.
1107 *
1108 * The sessions needed for a FAPI command will be created. If needed also the
1109 * primary key for session encryption will be created.
1110 *
1111 * @param[in] context The FAPI_CONTEXT storing the used handles.
1112 * @param[in] profile The FAPI profile will be used to adjust session parameters.
1113 * @param[in] hash_alg The hash algorithm used for the session.
1114 *
1115 * @retval TSS2_RC_SUCCESS on success.
1116 * @retval TSS2_FAPI_RC_IO_ERROR if an I/O error was encountered.
1117 * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated for path names.
1118 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
1119 * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
1120 * this function needs to be called again.
1121 * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
1122 * operation already pending.
1123 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
1124 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1125 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
1126 * the function.
1127 * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found
1128 * during authorization.
1129 * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
1130 * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback
1131 * is not set.
1132 * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
1133 * @retval TSS2_FAPI_RC_POLICY_UNKNOWN if policy search for a certain policy digest
1134 * was not successful.
1135 */
1136 TSS2_RC
ifapi_get_sessions_finish(FAPI_CONTEXT * context,const IFAPI_PROFILE * profile,TPMI_ALG_HASH hash_alg)1137 ifapi_get_sessions_finish(
1138 FAPI_CONTEXT *context,
1139 const IFAPI_PROFILE *profile,
1140 TPMI_ALG_HASH hash_alg)
1141 {
1142 TSS2_RC r;
1143
1144 switch (context->session_state) {
1145 statecase(context->session_state, SESSION_WAIT_FOR_PRIMARY);
1146 LOG_TRACE("**STATE** SESSION_WAIT_FOR_PRIMARY");
1147 r = ifapi_load_primary_finish(context, &context->srk_handle);
1148 return_try_again(r);
1149 return_if_error(r, "Load primary.");
1150 fallthrough;
1151
1152 statecase(context->session_state, SESSION_CREATE_SESSION);
1153 LOG_TRACE("**STATE** SESSION_CREATE_SESSION");
1154 if (!(context->session_flags & IFAPI_SESSION1)) {
1155 LOG_TRACE("finished");
1156 return TSS2_RC_SUCCESS;
1157 }
1158
1159 /* Initializing the first session for the caller */
1160
1161 r = ifapi_get_session_async(context->esys, context->srk_handle, profile,
1162 hash_alg);
1163 return_if_error_reset_state(r, "Create FAPI session async");
1164 fallthrough;
1165
1166 statecase(context->session_state, SESSION_WAIT_FOR_SESSION1);
1167 LOG_TRACE("**STATE** SESSION_WAIT_FOR_SESSION1");
1168 r = ifapi_get_session_finish(context->esys, &context->session1,
1169 context->session1_attribute_flags);
1170 return_try_again(r);
1171 return_if_error_reset_state(r, "Create FAPI session finish");
1172
1173 if (!(context->session_flags & IFAPI_SESSION2)) {
1174 LOG_TRACE("finished");
1175 return TSS2_RC_SUCCESS;
1176 }
1177
1178 /* Initializing the second session for the caller */
1179
1180 r = ifapi_get_session_async(context->esys, context->srk_handle, profile,
1181 profile->nameAlg);
1182 return_if_error_reset_state(r, "Create FAPI session async");
1183 fallthrough;
1184
1185 statecase(context->session_state, SESSION_WAIT_FOR_SESSION2);
1186 LOG_TRACE("**STATE** SESSION_WAIT_FOR_SESSION2");
1187 r = ifapi_get_session_finish(context->esys, &context->session2,
1188 context->session2_attribute_flags);
1189 return_try_again(r);
1190
1191 return_if_error_reset_state(r, "Create FAPI session finish");
1192 break;
1193
1194 statecasedefault(context->session_state);
1195 }
1196
1197 return TSS2_RC_SUCCESS;
1198 }
1199
1200 /** Merge profile already stored in FAPI context into a NV object template.
1201 *
1202 * The defaults for NV creation which are stored in the FAPI default profile
1203 * will be merged in the passed templates default values.
1204 *
1205 * @param[in] context The FAPI_CONTEXT with the default profile.
1206 * @param[in] template The template with the default values for the NV object.
1207 *
1208 * @retval TSS2_RC_SUCCESS on success.
1209 */
1210 TSS2_RC
ifapi_merge_profile_into_nv_template(FAPI_CONTEXT * context,IFAPI_NV_TEMPLATE * template)1211 ifapi_merge_profile_into_nv_template(
1212 FAPI_CONTEXT *context,
1213 IFAPI_NV_TEMPLATE *template)
1214 {
1215 const TPMA_NV extend_mask = TPM2_NT_EXTEND << TPMA_NV_TPM2_NT_SHIFT;
1216 const TPMA_NV counter_mask = TPM2_NT_COUNTER << TPMA_NV_TPM2_NT_SHIFT;
1217 const TPMA_NV bitfield_mask = TPM2_NT_BITS << TPMA_NV_TPM2_NT_SHIFT;
1218 const IFAPI_PROFILE *profile = &context->profiles.default_profile;
1219 size_t hash_size;
1220
1221 template->public.nameAlg = profile->nameAlg;
1222 if ((template->public.attributes & extend_mask) == extend_mask) {
1223 /* The size of the NV ram to be extended must be read from the
1224 profile */
1225 hash_size = ifapi_hash_get_digest_size(profile->nameAlg);
1226 template->public.dataSize = hash_size;
1227 } else if ((template->public.attributes & counter_mask) == counter_mask ||
1228 (template->public.attributes & bitfield_mask) == bitfield_mask) {
1229 /* For bit fields and counters only size 8 is possible */
1230 template->public.dataSize = 8;
1231 } else {
1232 /* For normal NV ram the passed size will be used. */
1233 template->public.dataSize = context->nv_cmd.numBytes;
1234 }
1235
1236 return TSS2_RC_SUCCESS;
1237 }
1238
1239 /** Merge profile already stored in FAPI context into a key template.
1240 *
1241 * The defaults for key creation which are stored in the FAPI default profile
1242 * will be merged in the passed templates default values.
1243 *
1244 * @param[in] profile The profile which will be used to adjust the template.
1245 * @param[in] template The template with the default values for the key object.
1246 *
1247 * @retval TSS2_RC_SUCCESS on success.
1248 */
1249 TSS2_RC
ifapi_merge_profile_into_template(const IFAPI_PROFILE * profile,IFAPI_KEY_TEMPLATE * template)1250 ifapi_merge_profile_into_template(
1251 const IFAPI_PROFILE *profile,
1252 IFAPI_KEY_TEMPLATE *template)
1253 {
1254 /* Merge profile parameters */
1255 template->public.publicArea.type = profile->type;
1256 template->public.publicArea.nameAlg = profile->nameAlg;
1257 if (profile->type == TPM2_ALG_RSA) {
1258 template->public.publicArea.parameters.rsaDetail.keyBits = profile->keyBits;
1259 template->public.publicArea.parameters.rsaDetail.exponent = profile->exponent;
1260 } else if (profile->type == TPM2_ALG_ECC) {
1261 template->public.publicArea.parameters.eccDetail.curveID = profile->curveID;
1262 template->public.publicArea.parameters.eccDetail.kdf.scheme = TPM2_ALG_NULL;
1263 }
1264
1265 /* Set remaining parameters depending on key type */
1266 if (template->public.publicArea.objectAttributes & TPMA_OBJECT_RESTRICTED) {
1267 if (template->public.publicArea.objectAttributes & TPMA_OBJECT_DECRYPT) {
1268 template->public.publicArea.parameters.asymDetail.symmetric =
1269 profile->sym_parameters;
1270 } else {
1271 template->public.publicArea.parameters.asymDetail.symmetric.algorithm =
1272 TPM2_ALG_NULL;
1273 }
1274 if (profile->type == TPM2_ALG_RSA) {
1275 if (template->public.publicArea.objectAttributes & TPMA_OBJECT_SIGN_ENCRYPT) {
1276 template->public.publicArea.parameters.rsaDetail.scheme.scheme =
1277 profile->rsa_signing_scheme.scheme;
1278 memcpy(&template->public.publicArea.parameters.rsaDetail.scheme.details,
1279 &profile->rsa_signing_scheme.details, sizeof(TPMU_ASYM_SCHEME));
1280 } else {
1281 template->public.publicArea.parameters.rsaDetail.scheme.scheme = TPM2_ALG_NULL;
1282 }
1283 } else if (profile->type == TPM2_ALG_ECC) {
1284 if (template->public.publicArea.objectAttributes & TPMA_OBJECT_SIGN_ENCRYPT) {
1285 template->public.publicArea.parameters.eccDetail.scheme.scheme =
1286 profile->ecc_signing_scheme.scheme;
1287 memcpy(&template->public.publicArea.parameters.eccDetail.scheme.details,
1288 &profile->ecc_signing_scheme.details, sizeof(TPMU_ASYM_SCHEME));
1289 } else {
1290 template->public.publicArea.parameters.eccDetail.scheme.scheme = TPM2_ALG_NULL;
1291 }
1292 } else {
1293 template->public.publicArea.parameters.asymDetail.scheme.scheme = TPM2_ALG_NULL;
1294 }
1295 } else {
1296 /* Non restricted key */
1297 template->public.publicArea.parameters.asymDetail.symmetric.algorithm =
1298 TPM2_ALG_NULL;
1299 template->public.publicArea.parameters.asymDetail.scheme.scheme = TPM2_ALG_NULL;
1300 }
1301 return TSS2_RC_SUCCESS;
1302 }
1303
1304 /** Convert absolute path to FAPI path which can be used as parameter for FAPI commands.
1305 *
1306 * Function converts the absolute path to a FAPI path.
1307 *
1308 * @param[in] keystore The used keystore.
1309 * @param[out] path FAPI key path.
1310 */
1311 static void
full_path_to_fapi_path(IFAPI_KEYSTORE * keystore,char * path)1312 full_path_to_fapi_path(IFAPI_KEYSTORE *keystore, char *path)
1313 {
1314 unsigned int start_pos, end_pos, i;
1315 const unsigned int path_length = strlen(path);
1316 size_t keystore_length = strlen(keystore->userdir);
1317 char fapi_path_delim;
1318
1319 start_pos = 0;
1320
1321 /* Check key store part of the path */
1322 if (strncmp(&path[0], keystore->userdir, keystore_length) == 0) {
1323 start_pos = strlen(keystore->userdir);
1324 } else {
1325 keystore_length = strlen(keystore->systemdir);
1326 if (strncmp(&path[0], keystore->systemdir, keystore_length) == 0)
1327 start_pos = strlen(keystore->systemdir);
1328 }
1329 if (!start_pos)
1330 return;
1331
1332 /* Shift FAPI path to the beginning. */
1333 end_pos = path_length - start_pos;
1334 memmove(&path[0], &path[start_pos], end_pos);
1335 size_t ip = 0;
1336 size_t lp = strlen(path);
1337
1338 /* Special handling for // */
1339 while (ip < lp) {
1340 if (strncmp(&path[ip], "//", 2) == 0) {
1341 memmove(&path[ip], &path[ip + 1], lp - ip);
1342 lp -= 1;
1343 } else {
1344 ip += 1;
1345 }
1346 }
1347
1348 /* Special handling for policy path were the name of the object file
1349 is part of the path. */
1350 if (ifapi_path_type_p(path, IFAPI_POLICY_PATH))
1351 fapi_path_delim = '.';
1352 else
1353 fapi_path_delim = IFAPI_FILE_DELIM_CHAR;
1354
1355 for (i = end_pos - 1; i > 0; i--) {
1356 if (path[i] == fapi_path_delim) {
1357 path[i] = '\0';
1358 break;
1359 }
1360 }
1361 }
1362
1363 /** Asynchronous preparation for loading a key and parent keys.
1364 *
1365 * The key loading is prepared. The pathname will be extended if possible and
1366 * a linked list with the directories will be created.
1367 *
1368 * @param[in,out] context The FAPI_CONTEXT.
1369 * @param[in] keyPath the key path without the parent directories
1370 * of the key store. (e.g. HE/EK, HS/SRK/mykey)
1371 *
1372 * @retval TSS2_RC_SUCCESS If the preparation is successful.
1373 * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated for path names.
1374 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
1375 * the function.
1376 */
1377 TSS2_RC
ifapi_load_keys_async(FAPI_CONTEXT * context,char const * keyPath)1378 ifapi_load_keys_async(FAPI_CONTEXT *context, char const *keyPath)
1379 {
1380 TSS2_RC r;
1381 NODE_STR_T *path_list;
1382 size_t path_length;
1383 char *fapi_key_path = NULL;
1384
1385 LOG_TRACE("Load key: %s", keyPath);
1386 fapi_key_path = strdup(keyPath);
1387 check_oom(fapi_key_path);
1388 full_path_to_fapi_path(&context->keystore, fapi_key_path);
1389 r = get_explicit_key_path(&context->keystore, fapi_key_path, &path_list);
1390 SAFE_FREE(fapi_key_path);
1391 return_if_error(r, "Compute explicit path.");
1392
1393 context->loadKey.path_list = path_list;
1394 path_length = ifapi_path_length(path_list);
1395 r = ifapi_load_key_async(context, path_length);
1396 return_if_error(r, "Load key async.");
1397
1398 return TSS2_RC_SUCCESS;
1399 }
1400
1401 /** Asynchronous finish function for loading a key.
1402 *
1403 * @param[in,out] context The FAPI_CONTEXT.
1404 * @param[in] flush_parent If false the parent of the key to be loaded
1405 * will not be flushed.
1406 * @param[out] handle The ESYS handle of the key.
1407 * @param[out] key_object The object which will be used for the
1408 * authorization of the loaded key.
1409 * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
1410 * this function needs to be called again.
1411 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1412 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
1413 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
1414 * the function.
1415 * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
1416 * operation already pending.
1417 * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found
1418 * during authorization.
1419 * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
1420 * @retval TSS2_FAPI_RC_IO_ERROR if an error occurred while accessing the
1421 * object store.
1422 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1423 * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback
1424 * is not set.
1425 * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
1426 * @retval TSS2_FAPI_RC_POLICY_UNKNOWN if policy search for a certain policy digest
1427 * was not successful.
1428 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
1429 */
1430 TSS2_RC
ifapi_load_keys_finish(FAPI_CONTEXT * context,bool flush_parent,ESYS_TR * handle,IFAPI_OBJECT ** key_object)1431 ifapi_load_keys_finish(
1432 FAPI_CONTEXT *context,
1433 bool flush_parent,
1434 ESYS_TR *handle,
1435 IFAPI_OBJECT **key_object)
1436 {
1437 TSS2_RC r;
1438
1439 r = ifapi_load_key_finish(context, flush_parent);
1440 if (r == TSS2_FAPI_RC_TRY_AGAIN)
1441 return r;
1442
1443 return_if_error(r, "Load keys");
1444
1445 *handle = context->loadKey.auth_object.handle;
1446 /* The current authorization object is the last key loaded and
1447 will be used. */
1448 *key_object = &context->loadKey.auth_object;
1449 free_string_list(context->loadKey.path_list);
1450 return TSS2_RC_SUCCESS;
1451 }
1452
1453 /** Initialize state machine for loading a key.
1454 *
1455 * @param[in,out] context for storing all state information.
1456 * @param[in] position the position of the key in path list stored in
1457 * context->loadKey.path_list.
1458 *
1459 * @retval TSS2_RC_SUCCESS on success.
1460 * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated for path names.
1461 */
1462 TSS2_RC
ifapi_load_key_async(FAPI_CONTEXT * context,size_t position)1463 ifapi_load_key_async(FAPI_CONTEXT *context, size_t position)
1464 {
1465 context->loadKey.state = LOAD_KEY_GET_PATH;
1466 context->loadKey.position = position;
1467 context->loadKey.key_list = NULL;
1468 context->loadKey.parent_handle = ESYS_TR_NONE;
1469 // context->loadKey.auth_object = NULL;
1470
1471 return TSS2_RC_SUCCESS;
1472 }
1473
1474 /** State machine for loading a key.
1475 *
1476 * A stack with all sup keys will be created and decremented during
1477 * the loading auf all keys.
1478 * The object of the loaded key will be stored in:
1479 * context->loadKey.auth_object
1480 *
1481 * @param[in,out] context for storing all state information.
1482 * @param[in] flush_parent If flush_parent is false parent is
1483 only flushed if a new parent is available.
1484 *
1485 * @retval TSS2_RC_SUCCESS If the loading of the key was successful.
1486 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
1487 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1488 * @retval TSS2_FAPI_RC_GENERAL_FAILURE If an internal error occurs, which is
1489 * not covered by other return codes.
1490 * @retval TSS2_FAPI_RC_BAD_VALUE If wrong values are detected during execution.
1491 * @retval TSS2_FAPI_RC_IO_ERROR If an error occurs during access to the policy
1492 * store.
1493 * @retval TSS2_FAPI_RC_PATH_NOT_FOUND If an object needed for loading or
1494 * authentication was not found.
1495 * @retval TSS2_FAPI_RC_POLICY_UNKNOWN If policy search for a certain policy digest was
1496 * not successful.
1497 * @retval TPM2_RC_BAD_AUTH If the authentication for an object needed for loading
1498 * fails.
1499 * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a needed authorization callback
1500 * is not defined.
1501 * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
1502 * this function needs to be called again.
1503 * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
1504 * operation already pending.
1505 * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
1506 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1507 * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
1508 */
1509 TSS2_RC
ifapi_load_key_finish(FAPI_CONTEXT * context,bool flush_parent)1510 ifapi_load_key_finish(FAPI_CONTEXT *context, bool flush_parent)
1511 {
1512 TSS2_RC r;
1513 NODE_STR_T *path_list = context->loadKey.path_list;
1514 size_t *position = &context->loadKey.position;
1515 IFAPI_OBJECT *key_object = NULL;
1516 IFAPI_KEY *key = NULL;
1517 ESYS_TR auth_session;
1518
1519 switch (context->loadKey.state) {
1520 statecase(context->loadKey.state, LOAD_KEY_GET_PATH);
1521 context->loadKey.key_path = NULL;
1522 /* Compute path name of key to be loaded. */
1523 r = ifapi_path_string_n(&context->loadKey.key_path, NULL, path_list, NULL,
1524 *position);
1525 return_if_error(r, "Compute key path.");
1526
1527 context->loadKey.key_object = ifapi_allocate_object(context);
1528 goto_if_null2(context->loadKey.key_object, "Allocating key", r,
1529 TSS2_FAPI_RC_MEMORY, error_cleanup);
1530
1531 goto_if_null2(context->loadKey.key_path, "Invalid path", r,
1532 TSS2_FAPI_RC_GENERAL_FAILURE,
1533 error_cleanup); /**< to avoid scan-build errors. */
1534
1535 /* Prepare key loading. */
1536 r = ifapi_keystore_load_async(&context->keystore, &context->io,
1537 context->loadKey.key_path);
1538 return_if_error2(r, "Could not open: %s", context->loadKey.key_path);
1539 fallthrough;
1540
1541 statecase(context->loadKey.state, LOAD_KEY_READ_KEY);
1542 goto_if_null2(context->loadKey.key_path, "Invalid path", r,
1543 TSS2_FAPI_RC_GENERAL_FAILURE,
1544 error_cleanup); /**< to avoid scan-build errors. */
1545
1546 key = &context->loadKey.key_object->misc.key;
1547
1548 r = ifapi_keystore_load_finish(&context->keystore, &context->io,
1549 context->loadKey.key_object);
1550 if (r != TSS2_RC_SUCCESS) {
1551 ifapi_cleanup_ifapi_object(context->loadKey.key_object);
1552 }
1553 return_try_again(r);
1554 return_if_error(r, "read_finish failed");
1555
1556 if (context->loadKey.key_object->objectType != IFAPI_KEY_OBJ)
1557 goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "%s is no key", error_cleanup,
1558 context->loadKey.key_path);
1559
1560 r = ifapi_initialize_object(context->esys, context->loadKey.key_object);
1561 goto_if_error_reset_state(r, "Initialize key object", error_cleanup);
1562
1563 SAFE_FREE(context->loadKey.key_path);
1564 context->loadKey.handle = context->loadKey.key_object->handle;
1565 if (context->loadKey.handle != ESYS_TR_NONE) {
1566 /* Persistent key could be desearialized keys can be loaded */
1567 r = ifapi_copy_ifapi_key_object(&context->loadKey.auth_object,
1568 context->loadKey.key_object);
1569 goto_if_error(r, "Could not copy key object", error_cleanup);
1570 ifapi_cleanup_ifapi_object(context->loadKey.key_object); context->loadKey.state = LOAD_KEY_LOAD_KEY;
1571
1572 return TSS2_FAPI_RC_TRY_AGAIN;
1573 }
1574
1575 if (key->private.size == 0) {
1576 /* Create a deep copy of the primary key */
1577 ifapi_cleanup_ifapi_key(key);
1578 r = ifapi_copy_ifapi_key(key, &context->createPrimary.pkey_object.misc.key);
1579 goto_if_error(r, "Could not copy primary key", error_cleanup);
1580 context->primary_state = PRIMARY_READ_HIERARCHY;
1581 context->loadKey.state = LOAD_KEY_WAIT_FOR_PRIMARY;
1582 return TSS2_FAPI_RC_TRY_AGAIN;
1583 }
1584 IFAPI_OBJECT * copyToPush = malloc(sizeof(IFAPI_OBJECT));
1585 goto_if_null(copyToPush, "Out of memory", TSS2_FAPI_RC_MEMORY, error_cleanup);
1586 r = ifapi_copy_ifapi_key_object(copyToPush, context->loadKey.key_object);
1587 if (r) {
1588 free(copyToPush);
1589 LOG_ERROR("Could not create a copy to push");
1590 goto error_cleanup;
1591 }
1592 /* Add object to the list of keys to be loaded. */
1593 r = push_object_to_list(copyToPush, &context->loadKey.key_list);
1594 if (r) {
1595 free(copyToPush);
1596 LOG_ERROR("Out of memory");
1597 goto error_cleanup;
1598 }
1599
1600 ifapi_cleanup_ifapi_object(context->loadKey.key_object);
1601
1602 *position -= 1;
1603 context->loadKey.state = LOAD_KEY_GET_PATH;
1604 return TSS2_FAPI_RC_TRY_AGAIN;
1605
1606 statecase(context->loadKey.state, LOAD_KEY_LOAD_KEY);
1607 if (!(context->loadKey.key_list)) {
1608 LOG_TRACE("All keys loaded.");
1609 return TSS2_RC_SUCCESS;
1610 }
1611
1612 /* if flush_parent is false parent is only flushed if a new parent
1613 is available */
1614 if (!flush_parent && context->loadKey.parent_handle != ESYS_TR_NONE) {
1615 r = Esys_FlushContext(context->esys, context->loadKey.parent_handle);
1616 goto_if_error_reset_state(r, "Flush object", error_cleanup);
1617 }
1618 fallthrough;
1619
1620 statecase(context->loadKey.state, LOAD_KEY_AUTHORIZE);
1621 key_object = context->loadKey.key_list->object;
1622 key = &key_object->misc.key;
1623 r = ifapi_authorize_object(context, &context->loadKey.auth_object, &auth_session);
1624 FAPI_SYNC(r, "Authorize key.", error_cleanup);
1625
1626 /* Store parent handle in context for usage in ChangeAuth if not persistent */
1627 context->loadKey.parent_handle = context->loadKey.handle;
1628 if (context->loadKey.auth_object.misc.key.persistent_handle)
1629 context->loadKey.parent_handle_persistent = true;
1630 else
1631 context->loadKey.parent_handle_persistent = false;
1632
1633 TPM2B_PRIVATE private;
1634
1635 private.size = key->private.size;
1636 memcpy(&private.buffer[0], key->private.buffer, key->private.size);
1637
1638 r = Esys_Load_Async(context->esys, context->loadKey.handle,
1639 auth_session,
1640 ESYS_TR_NONE, ESYS_TR_NONE,
1641 &private, &key->public);
1642 goto_if_error(r, "Load async", error_cleanup);
1643 fallthrough;
1644
1645 statecase(context->loadKey.state, LOAD_KEY_AUTH);
1646 r = Esys_Load_Finish(context->esys, &context->loadKey.handle);
1647 return_try_again(r);
1648 goto_if_error_reset_state(r, "Load", error_cleanup);
1649
1650 /* The current parent is flushed if not prohibited by flush parent */
1651 if (flush_parent && context->loadKey.auth_object.objectType == IFAPI_KEY_OBJ &&
1652 ! context->loadKey.auth_object.misc.key.persistent_handle) {
1653 r = Esys_FlushContext(context->esys, context->loadKey.auth_object.handle);
1654 goto_if_error_reset_state(r, "Flush object", error_cleanup);
1655
1656 }
1657 LOG_TRACE("New key used as auth object.");
1658 ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
1659 r = ifapi_copy_ifapi_key_object(&context->loadKey.auth_object,
1660 context->loadKey.key_list->object);
1661 goto_if_error(r, "Could not copy loaded key", error_cleanup);
1662 context->loadKey.auth_object.handle = context->loadKey.handle;
1663 IFAPI_OBJECT *top_obj = context->loadKey.key_list->object;
1664 ifapi_cleanup_ifapi_object(top_obj);
1665 SAFE_FREE(context->loadKey.key_list->object);
1666 r = pop_object_from_list(context, &context->loadKey.key_list);
1667 goto_if_error_reset_state(r, "Pop key failed.", error_cleanup);
1668
1669 if (context->loadKey.key_list) {
1670 /* Object can be cleaned if it's not the last */
1671 ifapi_free_object(context, &top_obj);
1672 }
1673
1674 context->loadKey.state = LOAD_KEY_LOAD_KEY;
1675 return TSS2_FAPI_RC_TRY_AGAIN;
1676
1677 statecase(context->loadKey.state, LOAD_KEY_WAIT_FOR_PRIMARY);
1678 r = ifapi_load_primary_finish(context, &context->loadKey.handle);
1679 return_try_again(r);
1680 goto_if_error(r, "CreatePrimary", error_cleanup);
1681
1682 /* Save the primary object for authorization */
1683 r = ifapi_copy_ifapi_key_object(&context->loadKey.auth_object,
1684 &context->createPrimary.pkey_object);
1685 goto_if_error(r, "Could not copy primary key", error_cleanup);
1686
1687 if (context->loadKey.key_list) {
1688 context->loadKey.state = LOAD_KEY_LOAD_KEY;
1689 return TSS2_FAPI_RC_TRY_AGAIN;
1690 } else {
1691 LOG_TRACE("success");
1692 ifapi_cleanup_ifapi_object(context->loadKey.key_object);
1693 ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
1694 return TSS2_RC_SUCCESS;
1695 }
1696 break;
1697
1698 statecasedefault(context->loadKey.state);
1699 }
1700
1701 error_cleanup:
1702 ifapi_free_object_list(context->loadKey.key_list);
1703 ifapi_cleanup_ifapi_object(context->loadKey.key_object);
1704 SAFE_FREE(context->loadKey.key_path);
1705 return r;
1706 }
1707
1708 /** Get the name alg corresponding to a FAPI object.
1709 *
1710 * @param[in] context The context with the default profile.
1711 * @param[in] object The object to be checked.
1712 * @retval TPMI_ALG_HASH The hash algorithm.
1713 * @retval 0 If no name alg can be assigned to the object.
1714 */
1715 static size_t
get_name_alg(FAPI_CONTEXT * context,IFAPI_OBJECT * object)1716 get_name_alg(FAPI_CONTEXT *context, IFAPI_OBJECT *object)
1717 {
1718 switch (object->objectType) {
1719 case IFAPI_KEY_OBJ:
1720 return object->misc.key.public.publicArea.nameAlg;
1721 case IFAPI_NV_OBJ:
1722 return object->misc.nv.public.nvPublic.nameAlg;
1723 case IFAPI_HIERARCHY_OBJ:
1724 return context->profiles.default_profile.nameAlg;
1725 default:
1726 return 0;
1727 }
1728 }
1729
1730 /** Check whether policy session has to be flushed.
1731 *
1732 * Policy sessions with cleared continue session flag are not flushed in error
1733 * cases. Therefore the return code will be checked and if a policy session was
1734 * used the session will be flushed if the command was not executed successfully.
1735 *
1736 * @param[in,out] context for storing all state information.
1737 * @param[in] session the session to be checked whether flush is needed.
1738 * @param[in] r The return code of the command using the session.
1739 */
1740 void
ifapi_flush_policy_session(FAPI_CONTEXT * context,ESYS_TR session,TSS2_RC r)1741 ifapi_flush_policy_session(FAPI_CONTEXT *context, ESYS_TR session, TSS2_RC r)
1742 {
1743 if (session != context->session1) {
1744 /* A policy session was used instead auf the default session. */
1745 if (r != TSS2_RC_SUCCESS) {
1746 Esys_FlushContext(context->esys, session);
1747 }
1748 }
1749 }
1750
1751 /** State machine to authorize a key, a NV object of a hierarchy.
1752 *
1753 * @param[in,out] context for storing all state information.
1754 * @param[in] object The FAPI object.
1755 * @param[out] session The session which can be used for object authorization.
1756 *
1757 * @retval TSS2_RC_SUCCESS If the authorization is successful
1758 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1759 * @retval TSS2_FAPI_RC_BAD_VALUE If wrong values are detected during execution.
1760 * @retval TSS2_FAPI_RC_IO_ERROR If an error occurs during access to the policy
1761 * store.
1762 * @retval TSS2_FAPI_RC_PATH_NOT_FOUND If a policy for a certain path was not found.
1763 * @retval TSS2_FAPI_RC_POLICY_UNKNOWN If policy search for a certain policy digest was
1764 * not successful.
1765 * @retval TPM2_RC_BAD_AUTH If the authentication for an object needed for the policy
1766 * execution fails.
1767 * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a needed authorization callback
1768 is not defined.
1769 * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
1770 * this function needs to be called again.
1771 * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
1772 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
1773 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
1774 * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
1775 */
1776 TSS2_RC
ifapi_authorize_object(FAPI_CONTEXT * context,IFAPI_OBJECT * object,ESYS_TR * session)1777 ifapi_authorize_object(FAPI_CONTEXT *context, IFAPI_OBJECT *object, ESYS_TR *session)
1778 {
1779 TSS2_RC r;
1780 TPMI_YES_NO auth_required;
1781
1782 LOG_DEBUG("Authorize object: %x", object->handle);
1783 switch (object->authorization_state) {
1784 statecase(object->authorization_state, AUTH_INIT)
1785 LOG_TRACE("**STATE** AUTH_INIT");
1786
1787 if (!policy_digest_size(object)) {
1788 /* No policy used authorization callbacks have to be called if necessary. */
1789 if (object_with_auth(object)) {
1790 r = ifapi_set_auth(context, object, "Authorize object");
1791 return_if_error(r, "Set auth value");
1792 }
1793 /* No policy session needed current fapi session can be used */
1794 if (context->session1 && context->session1 != ESYS_TR_NONE)
1795 *session = context->session1;
1796 else
1797 /* Use password session if session1 had not been created */
1798 *session = ESYS_TR_PASSWORD;
1799 break;
1800 }
1801 r = ifapi_policyutil_execute_prepare(context, get_name_alg(context, object)
1802 ,object->policy);
1803 return_if_error(r, "Prepare policy execution.");
1804
1805 /* Next state will switch from prev context to next context. */
1806 context->policy.util_current_policy = context->policy.util_current_policy->prev;
1807 object->authorization_state = AUTH_EXEC_POLICY;
1808 fallthrough;
1809
1810 statecase(object->authorization_state, AUTH_EXEC_POLICY)
1811 *session = ESYS_TR_NONE;
1812 r = ifapi_policyutil_execute(context, session);
1813 if (r == TSS2_FAPI_RC_TRY_AGAIN)
1814 return r;
1815
1816 return_if_error(r, "Execute policy.");
1817
1818 r = Esys_TRSess_GetAuthRequired(context->esys, *session,
1819 &auth_required);
1820 return_if_error(r, "GetAuthRequired");
1821
1822 /* Check whether PolicyCommand requiring authorization was executed */
1823 if (auth_required == TPM2_YES) {
1824 r = ifapi_set_auth(context, object, "Authorize object");
1825 goto_if_error(r, "Set auth value", error);
1826 }
1827 /* Clear continue session flag, so policy session will be flushed after authorization */
1828 r = Esys_TRSess_SetAttributes(context->esys, *session, 0, TPMA_SESSION_CONTINUESESSION);
1829 goto_if_error(r, "Esys_TRSess_SetAttributes", error);
1830 break;
1831
1832 general_failure(object->authorization_state)
1833 }
1834
1835 object->authorization_state = AUTH_INIT;
1836 return TSS2_RC_SUCCESS;
1837
1838 error:
1839 /* No policy call was executed session can be flushed */
1840 Esys_FlushContext(context->esys, *session);
1841 return r;
1842 }
1843
1844 /** State machine to write data to the NV ram of the TPM.
1845 *
1846 * The NV object will be read from object store and the data will be
1847 * written by one, or more than one if necessary, ESAPI calls to the NV ram of
1848 * the TPM.
1849 * The sub context nv_cmd will be prepared:
1850 * - data The buffer for the data which has to be written
1851 * - offset The current offset for writing
1852 * - numBytes The number of bytes which have to be written.
1853 *
1854 * @param[in,out] context for storing all state information.
1855 * @param[in] nvPath The fapi path of the NV object.
1856 * @param[in] param_offset The offset in the NV memory (will be stored in context).
1857 * @param[in] data The pointer to the data to be written.
1858 * @param[in] size The number of bytes to be written.
1859 *
1860 * @retval TSS2_RC_SUCCESS If data can be written.
1861 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
1862 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1863 * @retval TSS2_FAPI_RC_BAD_VALUE If wrong values are detected during execution.
1864 * @retval TSS2_FAPI_RC_GENERAL_FAILURE If an internal error occurs, which is
1865 + not covered by other return codes.
1866 * @retval TSS2_FAPI_RC_IO_ERROR If an error occurs during access to the object
1867 * store.
1868 * @retval TSS2_FAPI_RC_PATH_NOT_FOUND The nv object or an object needed for
1869 * authentication was not found.
1870 * @retval TSS2_FAPI_RC_POLICY_UNKNOWN If policy search for a certain policy digest was
1871 * not successful.
1872 * @retval TPM2_RC_BAD_AUTH If the authentication for an object needed for the
1873 * command execution fails.
1874 * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a needed authorization callback
1875 * is not defined.
1876 * @retval TSS2_FAPI_RC_BAD_PATH if the used path in inappropriate-
1877 * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
1878 * this function needs to be called again.
1879 * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
1880 * operation already pending.
1881 * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
1882 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1883 * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
1884 */
1885 TSS2_RC
ifapi_nv_write(FAPI_CONTEXT * context,char * nvPath,size_t param_offset,uint8_t const * data,size_t size)1886 ifapi_nv_write(
1887 FAPI_CONTEXT *context,
1888 char *nvPath,
1889 size_t param_offset,
1890 uint8_t const *data,
1891 size_t size)
1892 {
1893 TSS2_RC r = TSS2_RC_SUCCESS;
1894 ESYS_TR auth_index;
1895 ESYS_TR nv_index = context->nv_cmd.esys_handle;
1896 IFAPI_OBJECT *object = &context->nv_cmd.nv_object;
1897 IFAPI_OBJECT *auth_object = &context->nv_cmd.auth_object;
1898 TPM2B_MAX_NV_BUFFER *aux_data = (TPM2B_MAX_NV_BUFFER *)&context->aux_data;
1899 char *nv_file_name = NULL;
1900 ESYS_TR auth_session;
1901
1902 switch (context->nv_cmd.nv_write_state) {
1903 statecase(context->nv_cmd.nv_write_state, NV2_WRITE_INIT);
1904 memset(&context->nv_cmd.nv_object, 0, sizeof(IFAPI_OBJECT));
1905 context->nv_cmd.nvPath = nvPath;
1906 context->nv_cmd.offset = param_offset;
1907 context->nv_cmd.numBytes = size;
1908 context->nv_cmd.data = data;
1909 if (context->nv_cmd.numBytes > context->nv_buffer_max)
1910 aux_data->size = context->nv_buffer_max;
1911 else
1912 aux_data->size = context->nv_cmd.numBytes;
1913 context->nv_cmd.data_idx = 0;
1914
1915 /* Use calloc to ensure zero padding for write buffer. */
1916 context->nv_cmd.write_data = calloc(size, 1);
1917 goto_if_null2(context->nv_cmd.write_data, "Out of memory.", r,
1918 TSS2_FAPI_RC_MEMORY,
1919 error_cleanup);
1920 memcpy(context->nv_cmd.write_data, data, size);
1921 memcpy(&aux_data->buffer[0], &context->nv_cmd.data[0], aux_data->size);
1922
1923 /* Prepare reading of the key from keystore. */
1924 r = ifapi_keystore_load_async(&context->keystore, &context->io,
1925 context->nv_cmd.nvPath);
1926 return_if_error2(r, "Could not open: %s", context->nv_cmd.nvPath);
1927 fallthrough;
1928
1929 statecase(context->nv_cmd.nv_write_state, NV2_WRITE_READ);
1930 r = ifapi_keystore_load_finish(&context->keystore, &context->io, object);
1931 return_try_again(r);
1932 return_if_error(r, "read_finish failed");
1933
1934 if (object->objectType != IFAPI_NV_OBJ)
1935 goto_error(r, TSS2_FAPI_RC_BAD_PATH, "%s is no NV object.", error_cleanup,
1936 context->nv_cmd.nvPath);
1937
1938 r = ifapi_initialize_object(context->esys, object);
1939 goto_if_error_reset_state(r, "Initialize NV object", error_cleanup);
1940
1941 /* Store object info in context */
1942 nv_index = context->nv_cmd.nv_object.handle;
1943 context->nv_cmd.esys_handle = nv_index;
1944 context->nv_cmd.nv_obj = object->misc.nv;
1945
1946 /* Determine the object which will be uses for authorization. */
1947 if (object->misc.nv.public.nvPublic.attributes & TPMA_NV_PPWRITE) {
1948 ifapi_init_hierarchy_object(auth_object, ESYS_TR_RH_PLATFORM);
1949 auth_index = ESYS_TR_RH_PLATFORM;
1950 } else {
1951 if (object->misc.nv.public.nvPublic.attributes & TPMA_NV_OWNERWRITE) {
1952 ifapi_init_hierarchy_object(auth_object, ESYS_TR_RH_OWNER);
1953 auth_index = ESYS_TR_RH_OWNER;
1954 } else {
1955 auth_index = nv_index;
1956 }
1957 *auth_object = *object;
1958 }
1959 context->nv_cmd.auth_index = auth_index;
1960
1961 /* Get A session for authorizing the NV write operation. */
1962 r = ifapi_get_sessions_async(context, IFAPI_SESSION_GENEK | IFAPI_SESSION1,
1963 TPMA_SESSION_DECRYPT, 0);
1964 goto_if_error(r, "Create sessions", error_cleanup);
1965
1966 fallthrough;
1967
1968 statecase(context->nv_cmd.nv_write_state, NV2_WRITE_WAIT_FOR_SESSSION);
1969 r = ifapi_get_sessions_finish(context, &context->profiles.default_profile,
1970 object->misc.nv.public.nvPublic.nameAlg);
1971 return_try_again(r);
1972 goto_if_error_reset_state(r, " FAPI create session", error_cleanup);
1973
1974 fallthrough;
1975
1976 statecase(context->nv_cmd.nv_write_state, NV2_WRITE_AUTHORIZE);
1977 r = ifapi_authorize_object(context, auth_object, &auth_session);
1978 FAPI_SYNC(r, "Authorize NV object.", error_cleanup);
1979
1980 /* Prepare the writing to NV ram. */
1981 r = Esys_NV_Write_Async(context->esys,
1982 context->nv_cmd.auth_index,
1983 nv_index,
1984 auth_session,
1985 context->session2,
1986 ESYS_TR_NONE,
1987 aux_data,
1988 context->nv_cmd.data_idx);
1989 goto_if_error_reset_state(r, " Fapi_NvWrite_Async", error_cleanup);
1990
1991 if (!(object->misc.nv.public.nvPublic.attributes & TPMA_NV_NO_DA))
1992 context->nv_cmd.nv_write_state = NV2_WRITE_AUTH_SENT;
1993 else
1994 context->nv_cmd.nv_write_state = NV2_WRITE_NULL_AUTH_SENT;
1995
1996 context->nv_cmd.bytesRequested = aux_data->size;
1997
1998 fallthrough;
1999
2000 case NV2_WRITE_AUTH_SENT:
2001 case NV2_WRITE_NULL_AUTH_SENT:
2002 r = Esys_NV_Write_Finish(context->esys);
2003 return_try_again(r);
2004
2005 if ((r & ~TPM2_RC_N_MASK) == TPM2_RC_BAD_AUTH) {
2006 if (context->nv_cmd.nv_write_state == NV2_WRITE_NULL_AUTH_SENT) {
2007 IFAPI_OBJECT *auth_object = &context->nv_cmd.auth_object;
2008 r = ifapi_set_auth(context, auth_object, "NV Write");
2009 goto_if_error_reset_state(r, " Fapi_NvWrite_Finish", error_cleanup);
2010
2011 /* Prepare the writing to NV ram. */
2012 r = Esys_NV_Write_Async(context->esys,
2013 context->nv_cmd.auth_index,
2014 nv_index,
2015 (!context->policy.session
2016 || context->policy.session == ESYS_TR_NONE) ? context->session1 :
2017 context->policy.session,
2018 context->session2,
2019 ESYS_TR_NONE,
2020 aux_data,
2021 context->nv_cmd.data_idx);
2022 goto_if_error_reset_state(r, "FAPI NV_Write_Async", error_cleanup);
2023
2024 context->nv_cmd.nv_write_state = NV2_WRITE_AUTH_SENT;
2025 return TSS2_FAPI_RC_TRY_AGAIN;
2026 }
2027 }
2028 goto_if_error_reset_state(r, "FAPI NV_Write_Finish", error_cleanup);
2029
2030 context->nv_cmd.numBytes -= context->nv_cmd.bytesRequested;
2031
2032 if (context->nv_cmd.numBytes > 0) {
2033 /* Increment data idx with number of transmitted bytes. */
2034 context->nv_cmd.data_idx += aux_data->size;
2035 if (context->nv_cmd.numBytes > context->nv_buffer_max)
2036 aux_data->size = context->nv_buffer_max;
2037 else
2038 aux_data->size = context->nv_cmd.numBytes;
2039 memcpy(&aux_data->buffer[0],
2040 &context->nv_cmd.write_data[context->nv_cmd.data_idx],
2041 aux_data->size);
2042
2043 statecase(context->nv_cmd.nv_write_state, NV2_WRITE_AUTHORIZE2);
2044 r = ifapi_authorize_object(context, auth_object, &auth_session);
2045 FAPI_SYNC(r, "Authorize NV object.", error_cleanup);
2046
2047 /* Prepare the writing to NV ram */
2048 r = Esys_NV_Write_Async(context->esys,
2049 context->nv_cmd.auth_index,
2050 nv_index,
2051 auth_session,
2052 context->session2,
2053 ESYS_TR_NONE,
2054 aux_data,
2055 context->nv_cmd.data_idx);
2056 goto_if_error_reset_state(r, "FAPI NV_Write", error_cleanup);
2057
2058 context->nv_cmd.bytesRequested = aux_data->size;
2059 context->nv_cmd.nv_write_state = NV2_WRITE_AUTH_SENT;
2060 return TSS2_FAPI_RC_TRY_AGAIN;
2061
2062 }
2063 fallthrough;
2064
2065 statecase(context->nv_cmd.nv_write_state, NV2_WRITE_WRITE_PREPARE);
2066 /* Set written bit in keystore */
2067 context->nv_cmd.nv_object.misc.nv.public.nvPublic.attributes |= TPMA_NV_WRITTEN;
2068 /* Perform esys serialization if necessary */
2069 r = ifapi_esys_serialize_object(context->esys, &context->nv_cmd.nv_object);
2070 goto_if_error(r, "Prepare serialization", error_cleanup);
2071
2072 /* Start writing the NV object to the key store */
2073 r = ifapi_keystore_store_async(&context->keystore, &context->io,
2074 context->nv_cmd.nvPath,
2075 &context->nv_cmd.nv_object);
2076 goto_if_error_reset_state(r, "Could not open: %sh", error_cleanup,
2077 context->nv_cmd.nvPath);
2078 context->nv_cmd.nv_write_state = NV2_WRITE_WRITE;
2079 fallthrough;
2080
2081 statecase(context->nv_cmd.nv_write_state, NV2_WRITE_WRITE);
2082 /* Finish writing the NV object to the key store */
2083 r = ifapi_keystore_store_finish(&context->keystore, &context->io);
2084 return_try_again(r);
2085 return_if_error_reset_state(r, "write_finish failed");
2086
2087 LOG_DEBUG("success");
2088 r = TSS2_RC_SUCCESS;
2089
2090 context->nv_cmd.nv_write_state = NV2_WRITE_INIT;
2091 break;
2092
2093 statecasedefault(context->nv_cmd.nv_write_state);
2094 }
2095
2096 error_cleanup:
2097 SAFE_FREE(nv_file_name);
2098 SAFE_FREE(context->nv_cmd.write_data);
2099 return r;
2100 }
2101
2102 /** State machine to read data from the NV ram of the TPM.
2103 *
2104 * Context nv_cmd has to be prepared before the call of this function:
2105 * - auth_index The ESAPI handle of the authorization object.
2106 * - numBytes The number of bytes which should be read.
2107 * - esys_handle The ESAPI handle of the NV object.
2108 *
2109 * @param[in,out] context for storing all state information.
2110 * @param[out] data the data fetched from TPM.
2111 * @param[in,out] size The number of bytes requested and fetched.
2112 *
2113 * @retval TSS2_RC_SUCCESS If the data was read successfully.
2114 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
2115 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
2116 * @retval TSS2_FAPI_RC_BAD_VALUE If wrong values are detected during execution.
2117 * @retval TSS2_FAPI_RC_GENERAL_FAILURE If an internal error occurs, which is
2118 + not covered by other return codes.
2119 * @retval TSS2_FAPI_RC_IO_ERROR If an error occurs during access to the object
2120 * store.
2121 * @retval TSS2_FAPI_RC_PATH_NOT_FOUND If a policy for a certain path was not found.
2122 * @retval TSS2_FAPI_RC_POLICY_UNKNOWN If policy search for a certain policy digest was
2123 * not successful.
2124 * @retval TPM2_RC_BAD_AUTH If the authentication for an object needed for the
2125 * execution fails.
2126 * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a needed authorization callback
2127 * is not defined.
2128 * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
2129 * this function needs to be called again.
2130 * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
2131 * operation already pending.
2132 * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
2133 */
2134 TSS2_RC
ifapi_nv_read(FAPI_CONTEXT * context,uint8_t ** data,size_t * size)2135 ifapi_nv_read(
2136 FAPI_CONTEXT *context,
2137 uint8_t **data,
2138 size_t *size)
2139 {
2140 TSS2_RC r;
2141 UINT16 aux_size;
2142 TPM2B_MAX_NV_BUFFER *aux_data;
2143 UINT16 bytesRequested = context->nv_cmd.bytesRequested;
2144 size_t *numBytes = &context->nv_cmd.numBytes;
2145 ESYS_TR nv_index = context->nv_cmd.esys_handle;
2146 IFAPI_OBJECT *auth_object = &context->nv_cmd.auth_object;
2147 ESYS_TR session;
2148
2149 switch (context->nv_cmd.nv_read_state) {
2150 statecase(context->nv_cmd.nv_read_state, NV_READ_INIT);
2151 LOG_TRACE("NV_READ_INIT");
2152 context->nv_cmd.rdata = NULL;
2153 fallthrough;
2154
2155 statecase(context->nv_cmd.nv_read_state, NV_READ_AUTHORIZE);
2156 LOG_TRACE("NV_READ_AUTHORIZE");
2157 r = ifapi_authorize_object(context, auth_object, &session);
2158 FAPI_SYNC(r, "Authorize NV object.", error_cleanup);
2159
2160 if (*numBytes > context->nv_buffer_max)
2161 aux_size = context->nv_buffer_max;
2162 else
2163 aux_size = *numBytes;
2164
2165 /* Prepare the reading from NV ram. */
2166 r = Esys_NV_Read_Async(context->esys,
2167 context->nv_cmd.auth_index,
2168 nv_index,
2169 session,
2170 ESYS_TR_NONE,
2171 ESYS_TR_NONE,
2172 aux_size,
2173 0);
2174 goto_if_error_reset_state(r, " Fapi_NvRead_Async", error_cleanup);
2175
2176 context->nv_cmd.nv_read_state = NV_READ_AUTH_SENT;
2177 context->nv_cmd.bytesRequested = aux_size;
2178
2179 return TSS2_FAPI_RC_TRY_AGAIN;
2180
2181 statecase(context->nv_cmd.nv_read_state, NV_READ_AUTH_SENT);
2182 LOG_TRACE("NV_READ_NULL_AUTH_SENT");
2183 if (context->nv_cmd.rdata == NULL) {
2184 /* Allocate the data buffer if not already initialized. */
2185 LOG_TRACE("Allocate %zu bytes", *numBytes);
2186 context->nv_cmd.rdata = malloc(*numBytes);
2187 }
2188 *data = context->nv_cmd.rdata;
2189 goto_if_null(*data, "Malloc failed", TSS2_FAPI_RC_MEMORY, error_cleanup);
2190
2191 r = Esys_NV_Read_Finish(context->esys, &aux_data);
2192
2193 if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN)
2194 return TSS2_FAPI_RC_TRY_AGAIN;
2195
2196 goto_if_error_reset_state(r, "FAPI NV_Read_Finish", error_cleanup);
2197
2198 if (aux_data->size < bytesRequested)
2199 *numBytes = 0;
2200 else
2201 *numBytes -= aux_data->size;
2202 memcpy(*data + context->nv_cmd.data_idx, &aux_data->buffer[0],
2203 aux_data->size);
2204 context->nv_cmd.data_idx += aux_data->size;
2205 free(aux_data);
2206 if (*numBytes > 0) {
2207 statecase(context->nv_cmd.nv_read_state, NV_READ_AUTHORIZE2);
2208 r = ifapi_authorize_object(context, auth_object, &session);
2209 FAPI_SYNC(r, "Authorize NV object.", error_cleanup);
2210
2211 /* The reading of the NV data is not completed. The next
2212 reading will be prepared. */
2213 if (*numBytes > context->nv_buffer_max)
2214 aux_size = context->nv_buffer_max;
2215 else
2216 aux_size = *numBytes;
2217
2218 r = Esys_NV_Read_Async(context->esys,
2219 context->nv_cmd.auth_index,
2220 nv_index,
2221 session,
2222 ESYS_TR_NONE,
2223 ESYS_TR_NONE,
2224 aux_size,
2225 context->nv_cmd.data_idx);
2226 goto_if_error_reset_state(r, "FAPI NV_Read", error_cleanup);
2227 context->nv_cmd.bytesRequested = aux_size;
2228 context->nv_cmd.nv_read_state = NV_READ_AUTH_SENT;
2229 return TSS2_FAPI_RC_TRY_AGAIN;
2230 } else {
2231 *size = context->nv_cmd.data_idx;
2232 context->nv_cmd.nv_read_state = NV_READ_INIT;
2233 LOG_DEBUG("success");
2234 r = TSS2_RC_SUCCESS;
2235 break;
2236 }
2237 statecasedefault(context->nv_cmd.nv_read_state);
2238 }
2239
2240 error_cleanup:
2241 return r;
2242 }
2243
2244 #define min(X,Y) (X>Y)?Y:X
2245
2246 /** State machine to retrieve random data from TPM.
2247 *
2248 * If the buffer size exceeds the maximum size, several ESAPI calls are made.
2249 *
2250 * @param[in,out] context for storing all state information.
2251 * @param[in] numBytes Number of random bytes to be computed.
2252 * @param[out] data The random data.
2253 *
2254 * @retval TSS2_RC_SUCCESS If random data can be computed.
2255 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
2256 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
2257 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
2258 * the function.
2259 * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
2260 * this function needs to be called again.
2261 * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
2262 * operation already pending.
2263 */
2264 TSS2_RC
ifapi_get_random(FAPI_CONTEXT * context,size_t numBytes,uint8_t ** data)2265 ifapi_get_random(FAPI_CONTEXT *context, size_t numBytes, uint8_t **data)
2266 {
2267 TSS2_RC r;
2268 TPM2B_DIGEST *aux_data = NULL;
2269
2270 switch (context->get_random_state) {
2271 statecase(context->get_random_state, GET_RANDOM_INIT);
2272 context->get_random.numBytes = numBytes;
2273 context->get_random.data = calloc(context->get_random.numBytes, 1);
2274 context->get_random.idx = 0;
2275 return_if_null(context->get_random.data, "FAPI out of memory.",
2276 TSS2_FAPI_RC_MEMORY);
2277
2278 /* Prepare the creation of random data. */
2279 r = Esys_GetRandom_Async(context->esys,
2280 context->session1,
2281 ESYS_TR_NONE, ESYS_TR_NONE,
2282 min(context->get_random.numBytes, sizeof(TPMU_HA)));
2283 goto_if_error_reset_state(r, "FAPI GetRandom", error_cleanup);
2284 fallthrough;
2285
2286 statecase(context->get_random_state, GET_RANDOM_SENT);
2287 r = Esys_GetRandom_Finish(context->esys, &aux_data);
2288 return_try_again(r);
2289 goto_if_error_reset_state(r, "FAPI GetRandom_Finish", error_cleanup);
2290
2291 if (aux_data -> size > context->get_random.numBytes) {
2292 goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "TPM returned too many bytes",
2293 error_cleanup);
2294 }
2295
2296 /* Save created random data. */
2297 memcpy(context->get_random.data + context->get_random.idx, &aux_data->buffer[0],
2298 aux_data->size);
2299 context->get_random.numBytes -= aux_data->size;
2300 context->get_random.idx += aux_data->size;
2301 Esys_Free(aux_data);
2302 aux_data = NULL;
2303 if (context->get_random.numBytes > 0) {
2304
2305 /* Continue creaion of random data if needed. */
2306 r = Esys_GetRandom_Async(context->esys, context->session1, ESYS_TR_NONE,
2307 ESYS_TR_NONE, min(context->get_random.numBytes, sizeof(TPMU_HA)));
2308 goto_if_error_reset_state(r, "FAPI GetRandom", error_cleanup);
2309
2310 return TSS2_FAPI_RC_TRY_AGAIN;
2311 }
2312 break;
2313
2314 statecasedefault(context->get_random_state);
2315 }
2316
2317 *data = context->get_random.data;
2318
2319 LOG_DEBUG("success");
2320 context->get_random_state = GET_RANDOM_INIT;
2321 return TSS2_RC_SUCCESS;
2322
2323 error_cleanup:
2324 if (aux_data)
2325 Esys_Free(aux_data);
2326 context->get_random_state = GET_RANDOM_INIT;
2327 if (context->get_random.data != NULL)
2328 SAFE_FREE(context->get_random.data);
2329 return r;
2330 }
2331
2332 /** Load a key and initialize profile and session for ESAPI execution.
2333 *
2334 * This state machine prepares the session for key loading. Some
2335 * session related parameters will be taken from profile.
2336 *
2337 * @param[in,out] context The FAPI_CONTEXT.
2338 * @param[in] keyPath the key path without the parent directories
2339 * of the key store. (e.g. HE/EK, HS/SRK/mykey)
2340 * @param[out] key_object The callee allocated internal representation
2341 * of a key object.
2342 *
2343 * @retval TSS2_RC_SUCCESS If the key was loaded successfully.
2344 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
2345 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
2346 * @retval TSS2_FAPI_RC_GENERAL_FAILURE If an internal error occurs, which is
2347 * not covered by other return codes.
2348 * @retval TSS2_FAPI_RC_BAD_VALUE If wrong values are detected during execution.
2349 * @retval TSS2_FAPI_RC_IO_ERROR If an error occurs during access to the object
2350 * store.
2351 * @retval TSS2_FAPI_RC_PATH_NOT_FOUND If a policy or key was not found.
2352 * @retval TSS2_FAPI_RC_POLICY_UNKNOWN If policy search for a certain policy digest was
2353 * not successful.
2354 * @retval TPM2_RC_BAD_AUTH If the authentication for an object needed for policy
2355 * execution fails.
2356 * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a needed authorization callback
2357 is not defined.
2358 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
2359 * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
2360 * this function needs to be called again.
2361 * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
2362 * operation already pending.
2363 * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
2364 * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
2365 */
2366 TSS2_RC
ifapi_load_key(FAPI_CONTEXT * context,char const * keyPath,IFAPI_OBJECT ** key_object)2367 ifapi_load_key(
2368 FAPI_CONTEXT *context,
2369 char const *keyPath,
2370 IFAPI_OBJECT **key_object)
2371 {
2372 TSS2_RC r;
2373 const IFAPI_PROFILE *profile;
2374
2375 return_if_null(keyPath, "Bad reference for key path.",
2376 TSS2_FAPI_RC_BAD_REFERENCE);
2377
2378 switch (context->Key_Sign.state) {
2379 statecase(context->Key_Sign.state, SIGN_INIT);
2380 context->Key_Sign.keyPath = keyPath;
2381
2382 /* Prepare the session creation. */
2383 r = ifapi_get_sessions_async(context,
2384 IFAPI_SESSION_GENEK | IFAPI_SESSION1,
2385 TPMA_SESSION_DECRYPT, 0);
2386 goto_if_error_reset_state(r, "Create sessions", error_cleanup);
2387 fallthrough;
2388
2389 statecase(context->Key_Sign.state, SIGN_WAIT_FOR_SESSION);
2390 r = ifapi_profiles_get(&context->profiles, context->Key_Sign.keyPath, &profile);
2391 goto_if_error_reset_state(r, "Reading profile data", error_cleanup);
2392
2393 r = ifapi_get_sessions_finish(context, profile, profile->nameAlg);
2394 return_try_again(r);
2395 goto_if_error_reset_state(r, " FAPI create session", error_cleanup);
2396
2397 /* Prepare the key loading. */
2398 r = ifapi_load_keys_async(context, context->Key_Sign.keyPath);
2399 goto_if_error(r, "Load keys.", error_cleanup);
2400 fallthrough;
2401
2402 statecase(context->Key_Sign.state, SIGN_WAIT_FOR_KEY);
2403 r = ifapi_load_keys_finish(context, IFAPI_FLUSH_PARENT,
2404 &context->Key_Sign.handle,
2405 key_object);
2406 return_try_again(r);
2407 goto_if_error_reset_state(r, " Load key.", error_cleanup);
2408
2409 context->Key_Sign.state = SIGN_INIT;
2410 break;
2411
2412 statecasedefault(context->Key_Sign.state);
2413 }
2414
2415 error_cleanup:
2416 return r;
2417 }
2418
2419 /** State machine for signing operation.
2420 *
2421 * The key used for signing will be authorized and the signing of the passed data
2422 * will be executed.
2423 *
2424 * @param[in,out] context The FAPI_CONTEXT.
2425 * @param[in] sig_key_object The Fapi key object which will be used to
2426 * sign the passed digest.
2427 * @param[in] padding is the padding algorithm used. Possible values are RSA_SSA,
2428 * RSA_PPSS (case insensitive). padding MAY be NULL.
2429 * @param[in] digest is the data to be signed, already hashed.
2430 * digest MUST NOT be NULL.
2431 * @param[out] tpm_signature returns the signature in binary form (DER format).
2432 * tpm_signature MUST NOT be NULL (callee-allocated).
2433 * @param[out] publicKey is the public key of the signing key in PEM format.
2434 * publicKey is callee allocated and MAY be NULL.
2435 * @param[out] certificate is the certificate associated with the signing key
2436 * in PEM format. certificate MAY be NULL.
2437 *
2438 * @retval TSS2_RC_SUCCESS If the signing was successful.
2439 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
2440 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
2441 * @retval TSS2_FAPI_RC_GENERAL_FAILURE If an internal error occurs, which is
2442 * not covered by other return codes.
2443 * @retval TSS2_FAPI_RC_BAD_VALUE If wrong values are detected during execution.
2444 * @retval TSS2_FAPI_RC_IO_ERROR If an error occurs during access to the policy
2445 * store.
2446 * @retval TSS2_FAPI_RC_PATH_NOT_FOUND If a policy for a certain path was not found.
2447 * @retval TSS2_FAPI_RC_POLICY_UNKNOWN If policy search for a certain policy digest was
2448 * not successful.
2449 * @retval TSS2_FAPI_RC_BAD_TEMPLATE In a invalid policy is loaded during execution.
2450 * @retval TPM2_RC_BAD_AUTH If the authentication for an object needed for policy
2451 * execution fails.
2452 * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a needed authorization callback
2453 * is not defined.
2454 * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
2455 * this function needs to be called again.
2456 * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
2457 * operation already pending.
2458 * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
2459 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
2460 */
2461 TSS2_RC
ifapi_key_sign(FAPI_CONTEXT * context,IFAPI_OBJECT * sig_key_object,char const * padding,TPM2B_DIGEST * digest,TPMT_SIGNATURE ** tpm_signature,char ** publicKey,char ** certificate)2462 ifapi_key_sign(
2463 FAPI_CONTEXT *context,
2464 IFAPI_OBJECT *sig_key_object,
2465 char const *padding,
2466 TPM2B_DIGEST *digest,
2467 TPMT_SIGNATURE **tpm_signature,
2468 char **publicKey,
2469 char **certificate)
2470 {
2471 TSS2_RC r;
2472 TPMT_SIG_SCHEME sig_scheme;
2473 ESYS_TR session;
2474
2475 TPMT_TK_HASHCHECK hash_validation = {
2476 .tag = TPM2_ST_HASHCHECK,
2477 .hierarchy = TPM2_RH_OWNER,
2478 };
2479 memset(&hash_validation.digest, 0, sizeof(TPM2B_DIGEST));
2480
2481 switch (context->Key_Sign.state) {
2482 statecase(context->Key_Sign.state, SIGN_INIT);
2483 sig_key_object = context->Key_Sign.key_object;
2484
2485 r = ifapi_authorize_object(context, sig_key_object, &session);
2486 FAPI_SYNC(r, "Authorize signature key.", cleanup);
2487
2488 context->policy.session = session;
2489
2490 r = ifapi_get_sig_scheme(context, sig_key_object, padding, digest, &sig_scheme);
2491 goto_if_error(r, "Get signature scheme", cleanup);
2492
2493 /* Prepare the signing operation. */
2494 r = Esys_Sign_Async(context->esys,
2495 context->Key_Sign.handle,
2496 session,
2497 ESYS_TR_NONE, ESYS_TR_NONE,
2498 digest,
2499 &sig_scheme,
2500 &hash_validation);
2501 goto_if_error(r, "Error: Sign", cleanup);
2502 fallthrough;
2503
2504 statecase(context->Key_Sign.state, SIGN_AUTH_SENT);
2505 context->Key_Sign.signature = NULL;
2506 r = Esys_Sign_Finish(context->esys,
2507 &context->Key_Sign.signature);
2508 return_try_again(r);
2509 ifapi_flush_policy_session(context, context->policy.session, r);
2510 goto_if_error(r, "Error: Sign", cleanup);
2511
2512 /* Prepare the flushing of the signing key. */
2513 r = Esys_FlushContext_Async(context->esys, context->Key_Sign.handle);
2514 goto_if_error(r, "Error: FlushContext", cleanup);
2515 fallthrough;
2516
2517 statecase(context->Key_Sign.state, SIGN_WAIT_FOR_FLUSH);
2518 r = Esys_FlushContext_Finish(context->esys);
2519 return_try_again(r);
2520 goto_if_error(r, "Error: Sign", cleanup);
2521
2522 int pem_size;
2523 if (publicKey) {
2524 /* Convert internal key object to PEM format. */
2525 r = ifapi_pub_pem_key_from_tpm(&sig_key_object->misc.key.public,
2526 publicKey,
2527 &pem_size);
2528 goto_if_error(r, "Conversion pub key to PEM failed", cleanup);
2529 }
2530 context->Key_Sign.handle = ESYS_TR_NONE;
2531 *tpm_signature = context->Key_Sign.signature;
2532 if (certificate) {
2533 *certificate = strdup(context->Key_Sign.key_object->misc.key.certificate);
2534 goto_if_null(*certificate, "Out of memory.",
2535 TSS2_FAPI_RC_MEMORY, cleanup);
2536 }
2537 context->Key_Sign.state = SIGN_INIT;
2538 LOG_TRACE("success");
2539 r = TSS2_RC_SUCCESS;
2540 break;
2541
2542 statecasedefault(context->Key_Sign.state);
2543 }
2544
2545 cleanup:
2546 if (context->Key_Sign.handle != ESYS_TR_NONE)
2547 Esys_FlushContext(context->esys, context->Key_Sign.handle);
2548 ifapi_cleanup_ifapi_object(context->Key_Sign.key_object);
2549 return r;
2550 }
2551
2552 /** Get json encoding for FAPI object.
2553 *
2554 * A json representation which can be used for exporting of a FAPI object will
2555 * be created.
2556 *
2557 * @param[in] context The FAPI_CONTEXT.
2558 * @param[in] object The object to be serialized.
2559 * @param[out] json_string The json string created by the deserialzation
2560 * function (callee-allocated).
2561 *
2562 * @retval TSS2_RC_SUCCESS If the serialization was successful.
2563 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
2564 * @retval TSS2_FAPI_RC_BAD_VALUE If wrong values are detected during
2565 * serialization.
2566 * @retval TSS2_FAPI_RC_BAD_REFERENCE If a NULL pointer was passed for
2567 * the object.
2568 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
2569 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
2570 */
2571 TSS2_RC
ifapi_get_json(FAPI_CONTEXT * context,IFAPI_OBJECT * object,char ** json_string)2572 ifapi_get_json(FAPI_CONTEXT *context, IFAPI_OBJECT *object, char **json_string)
2573 {
2574 TSS2_RC r = TSS2_RC_SUCCESS;
2575 json_object *jso = NULL;
2576
2577 /* Perform esys serialization if necessary */
2578 r = ifapi_esys_serialize_object(context->esys, object);
2579 goto_if_error(r, "Prepare serialization", cleanup);
2580
2581 r = ifapi_json_IFAPI_OBJECT_serialize(object, &jso);
2582 return_if_error(r, "Serialize duplication object");
2583
2584 *json_string = strdup(json_object_to_json_string_ext(jso,
2585 JSON_C_TO_STRING_PRETTY));
2586 goto_if_null2(*json_string, "Converting json to string", r, TSS2_FAPI_RC_MEMORY,
2587 cleanup);
2588
2589 cleanup:
2590 if (jso)
2591 json_object_put(jso);
2592 return r;
2593 }
2594
2595 /** Serialize persistent objects into buffer of keystore object.
2596 *
2597 * NV objects and persistent keys will serialized via the ESYS API to
2598 * enable reconstruction durinng loading from keystore.
2599 *
2600 * @param[in] ectx The ESAPI context.
2601 * @param[in,out] object The nv object or the key.
2602 * @retval TSS2_RC_SUCCESS if the function call was a success.
2603 */
2604 TSS2_RC
ifapi_esys_serialize_object(ESYS_CONTEXT * ectx,IFAPI_OBJECT * object)2605 ifapi_esys_serialize_object(ESYS_CONTEXT *ectx, IFAPI_OBJECT *object)
2606 {
2607 TSS2_RC r = TSS2_RC_SUCCESS;
2608 IFAPI_KEY *key_object = NULL;
2609 IFAPI_NV *nv_object;
2610
2611 switch (object->objectType) {
2612 case IFAPI_NV_OBJ:
2613 nv_object = &object->misc.nv;
2614 if (nv_object->serialization.buffer != NULL) {
2615 /* Cleanup old buffer */
2616 Fapi_Free(nv_object->serialization.buffer);
2617 nv_object->serialization.buffer = NULL;
2618 }
2619 r = Esys_TR_Serialize(ectx, object->handle,
2620 &nv_object->serialization.buffer,
2621 &nv_object->serialization.size);
2622 return_if_error(r, "Error serialize esys object");
2623 break;
2624
2625 case IFAPI_KEY_OBJ:
2626 key_object = &object->misc.key;
2627 key_object->serialization.size = 0;
2628 if (key_object->serialization.buffer != NULL) {
2629 /* Cleanup old buffer */
2630 Fapi_Free(key_object->serialization.buffer);
2631 key_object->serialization.buffer = NULL;
2632 }
2633 if (object->handle != ESYS_TR_NONE && key_object->persistent_handle) {
2634 key_object->serialization.buffer = NULL;
2635 r = Esys_TR_Serialize(ectx, object->handle,
2636 &key_object->serialization.buffer,
2637 &key_object->serialization.size);
2638 return_if_error(r, "Error serialize esys object");
2639 }
2640 break;
2641
2642 default:
2643 /* Nothing to be done */
2644 break;
2645 }
2646 return TSS2_RC_SUCCESS;
2647 }
2648
2649 /** Initialize the part of an IFAPI_OBJECT which is not serialized.
2650 *
2651 * For persistent objects the correspodning ESYS object will be created.
2652 *
2653 * @param[in,out] ectx The ESYS context.
2654 * @param[out] object the deserialzed binary object.
2655 * @retval TSS2_RC_SUCCESS if the function call was a success.
2656 * @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
2657 */
2658 TSS2_RC
ifapi_initialize_object(ESYS_CONTEXT * ectx,IFAPI_OBJECT * object)2659 ifapi_initialize_object(
2660 ESYS_CONTEXT *ectx,
2661 IFAPI_OBJECT *object)
2662 {
2663 TSS2_RC r = TSS2_RC_SUCCESS;
2664 ESYS_TR handle;
2665
2666 switch (object->objectType) {
2667 case IFAPI_NV_OBJ:
2668 if (object->misc.nv.serialization.size > 0) {
2669 r = Esys_TR_Deserialize(ectx, &object->misc.nv.serialization.buffer[0],
2670 object->misc.nv.serialization.size, &handle);
2671 goto_if_error(r, "Error dserialize esys object", cleanup);
2672 } else {
2673 handle = ESYS_TR_NONE;
2674 }
2675 object->authorization_state = AUTH_INIT;
2676 object->handle = handle;
2677 break;
2678
2679 case IFAPI_KEY_OBJ:
2680 if (object->misc.key.serialization.size > 0) {
2681 r = Esys_TR_Deserialize(ectx, &object->misc.key.serialization.buffer[0],
2682 object->misc.key.serialization.size, &handle);
2683 goto_if_error(r, "Error deserialize esys object", cleanup);
2684 } else {
2685 handle = ESYS_TR_NONE;
2686 }
2687 object->authorization_state = AUTH_INIT;
2688 object->handle = handle;
2689 break;
2690
2691 default:
2692 /* Nothing to be done */
2693 break;
2694 }
2695
2696 return r;
2697
2698 cleanup:
2699 SAFE_FREE(object->policy);
2700 return r;
2701 }
2702
2703 /** Prepare key creation with an auth value.
2704 *
2705 * The auth value will be copied int the FAPI context for later use in key creation.
2706 *
2707 * @param[in,out] context The FAPI_CONTEXT.
2708 * @param[in] keyPath the key path without the parent directories
2709 * of the key store. (e.g. HE/EK, HS/SRK/mykey)
2710 * @param[in] policyPath identifies the policy to be associated with the new key.
2711 * policyPath MAY be NULL. If policyPath is NULL then no policy will
2712 * be associated with the key.
2713 * @param[in] authValue The authentication value of the key.
2714 *
2715 * @retval TSS2_RC_SUCCESS If the preparation was successful.
2716 * @retval TSS2_FAPI_RC_PATH_ALREADY_EXISTS If the object with does already exist in
2717 * keystore.
2718 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
2719 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
2720 * the function.
2721 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
2722 * @retval TSS2_FAPI_RC_NO_TPM if FAPI was initialized in no-TPM-mode via its
2723 * config file.
2724 * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
2725 * operation already pending.
2726 */
2727 TSS2_RC
ifapi_key_create_prepare_auth(FAPI_CONTEXT * context,char const * keyPath,char const * policyPath,char const * authValue)2728 ifapi_key_create_prepare_auth(
2729 FAPI_CONTEXT *context,
2730 char const *keyPath,
2731 char const *policyPath,
2732 char const *authValue)
2733 {
2734 TSS2_RC r;
2735
2736 memset(&context->cmd.Key_Create.inSensitive, 0, sizeof(TPM2B_SENSITIVE_CREATE));
2737 if (authValue) {
2738 /* Copy the auth value */
2739 if (strlen(authValue) > sizeof(TPMU_HA)) {
2740 return_error(TSS2_FAPI_RC_BAD_VALUE, "Password too long.");
2741 }
2742 memcpy(&context->cmd.Key_Create.inSensitive.sensitive.userAuth.buffer,
2743 authValue, strlen(authValue));
2744 context->cmd.Key_Create.inSensitive.sensitive.userAuth.size = strlen(authValue);
2745 }
2746 context->cmd.Key_Create.inSensitive.sensitive.data.size = 0;
2747 r = ifapi_key_create_prepare(context, keyPath, policyPath);
2748 return r;
2749 }
2750
2751 /** Prepare key creation with an auth value and sensitive data.
2752 *
2753 * The auth value and the sensitive data will be copied int the FAPI context
2754 * for later use in key creation.
2755 *
2756 * @param[in,out] context The FAPI_CONTEXT.
2757 * @param[in] keyPath the key path without the parent directories
2758 * of the key store. (e.g. HE/EK, HS/SRK/mykey)
2759 * @param[in] policyPath identifies the policy to be associated with the new key.
2760 * policyPath MAY be NULL. If policyPath is NULL then no policy will
2761 * be associated with the key.
2762 * @param[in] dataSize The size of the sensitive data.
2763 * @param[in] authValue The authentication value of the key.
2764 * @param[in] data The sensitive data.
2765 *
2766 * @retval TSS2_RC_SUCCESS If the preparation was successful.
2767 * @retval TSS2_FAPI_RC_PATH_ALREADY_EXISTS If the object with does already exist in
2768 * keystore.
2769 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
2770 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
2771 * the function.
2772 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
2773 * @retval TSS2_FAPI_RC_NO_TPM if FAPI was initialized in no-TPM-mode via its
2774 * config file.
2775 * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
2776 * operation already pending.
2777 */
2778 TSS2_RC
ifapi_key_create_prepare_sensitive(FAPI_CONTEXT * context,char const * keyPath,char const * policyPath,size_t dataSize,char const * authValue,uint8_t const * data)2779 ifapi_key_create_prepare_sensitive(
2780 FAPI_CONTEXT *context,
2781 char const *keyPath,
2782 char const *policyPath,
2783 size_t dataSize,
2784 char const *authValue,
2785 uint8_t const *data)
2786 {
2787 TSS2_RC r;
2788
2789 memset(&context->cmd.Key_Create.inSensitive, 0, sizeof(TPM2B_SENSITIVE_CREATE));
2790 if (dataSize > sizeof(TPMU_HA) || dataSize == 0) {
2791 return_error(TSS2_FAPI_RC_BAD_VALUE, "Data to big or equal zero.");
2792 }
2793 if (data)
2794 /* Copy the sensitive data */
2795 memcpy(&context->cmd.Key_Create.inSensitive.sensitive.data.buffer,
2796 data, dataSize);
2797 context->cmd.Key_Create.inSensitive.sensitive.data.size = dataSize;
2798 if (authValue) {
2799 /* Copy the auth value. */
2800 if (strlen(authValue) > sizeof(TPMU_HA)) {
2801 return_error(TSS2_FAPI_RC_BAD_VALUE, "Password too long.");
2802 }
2803 memcpy(&context->cmd.Key_Create.inSensitive.sensitive.userAuth.buffer,
2804 authValue, strlen(authValue));
2805 context->cmd.Key_Create.inSensitive.sensitive.userAuth.size = strlen(authValue);
2806 }
2807 r = ifapi_key_create_prepare(context, keyPath, policyPath);
2808 return r;
2809 }
2810
2811 /** Prepare key creation if possible.
2812 *
2813 * It will be checked whether the object already exists in key store and the FAPI context
2814 * will be initialized appropriate for key creation.
2815 *
2816 * @param[in,out] context The FAPI_CONTEXT.
2817 * @param[in] keyPath the key path without the parent directories
2818 * of the key store. (e.g. HE/EK, HS/SRK/mykey)
2819 * @param[in] policyPath identifies the policy to be associated with the new key.
2820 * policyPath MAY be NULL. If policyPath is NULL then no policy will
2821 * be associated with the key.
2822 *
2823 * @retval TSS2_RC_SUCCESS If the preparation was successful.
2824 * @retval TSS2_FAPI_RC_PATH_ALREADY_EXISTS If the object with does already exist in
2825 * keystore.
2826 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
2827 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
2828 * @retval TSS2_FAPI_RC_NO_TPM if FAPI was initialized in no-TPM-mode via its
2829 * config file.
2830 * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
2831 * operation already pending.
2832 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
2833 * the function.
2834 */
2835 TSS2_RC
ifapi_key_create_prepare(FAPI_CONTEXT * context,char const * keyPath,char const * policyPath)2836 ifapi_key_create_prepare(
2837 FAPI_CONTEXT *context,
2838 char const *keyPath,
2839 char const *policyPath)
2840 {
2841 TSS2_RC r;
2842 IFAPI_OBJECT *object = &context->cmd.Key_Create.object;
2843 NODE_STR_T *path_list = NULL;
2844
2845 LOG_TRACE("call");
2846 r = ifapi_session_init(context);
2847 return_if_error(r, "Initialize Key_Create");
2848
2849 /* First check whether an existing object would be overwritten */
2850 r = ifapi_keystore_check_overwrite(&context->keystore, &context->io,
2851 keyPath);
2852 return_if_error2(r, "Check overwrite %s", keyPath);
2853
2854 context->srk_handle = 0;
2855
2856 /* Clear the memory used for the the new key object */
2857 memset(&context->cmd.Key_Create.outsideInfo, 0, sizeof(TPM2B_DATA));
2858 memset(&context->cmd.Key_Create.creationPCR, 0, sizeof(TPML_PCR_SELECTION));
2859 memset(object, 0, sizeof(IFAPI_OBJECT));
2860
2861 strdup_check(context->cmd.Key_Create.policyPath, policyPath, r, error);
2862 strdup_check(context->cmd.Key_Create.keyPath, keyPath, r, error);
2863 r = get_explicit_key_path(&context->keystore, keyPath, &path_list);
2864 return_if_error(r, "Compute explicit path.");
2865
2866 context->loadKey.path_list = path_list;
2867 char *file;
2868 r = ifapi_path_string(&file, NULL, path_list, NULL);
2869 goto_if_error(r, "Compute explicit path.", error);
2870
2871 LOG_DEBUG("Explicit key path: %s", file);
2872
2873 free(file);
2874
2875 context->cmd.Key_Create.state = KEY_CREATE_INIT;
2876
2877 return TSS2_RC_SUCCESS;
2878
2879 error:
2880 free_string_list(path_list);
2881 return r;
2882 }
2883
2884 /** State machine for key creation.
2885 *
2886 * The function for the preparation of the key have to called before the state machine can
2887 * be activated. The linked list for the used directories must be available in the
2888 * FAPI context.
2889 * It will be checked whether the object already exists in key store and the FAPI context
2890 * will be initialized appropriate for key creation.
2891 *
2892 * @param[in,out] context The FAPI_CONTEXT.
2893 * @param[in] template The template which defines the key attributes and whether the
2894 * key will be persistent.
2895 *
2896 * @retval TSS2_RC_SUCCESS If the key could be generated.
2897 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
2898 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
2899 * @retval TSS2_FAPI_RC_GENERAL_FAILURE If an internal error occurs, which is
2900 * not covered by other return codes.
2901 * @retval TSS2_FAPI_RC_BAD_VALUE If wrong values are detected during execution.
2902 * @retval TSS2_FAPI_RC_IO_ERROR If an error occurs during access to the policy
2903 * store.
2904 * @retval TSS2_FAPI_RC_PATH_NOT_FOUND If an object needed for creation or
2905 authentication was not found.
2906 * @retval TSS2_FAPI_RC_POLICY_UNKNOWN If policy search for a certain policy digest was
2907 * not successful.
2908 * @retval TPM2_RC_BAD_AUTH If the authentication for an object needed for creation
2909 * fails.
2910 * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a needed authorization callback
2911 * is not defined.
2912 * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
2913 * this function needs to be called again.
2914 * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
2915 * operation already pending.
2916 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
2917 */
2918 TSS2_RC
ifapi_key_create(FAPI_CONTEXT * context,IFAPI_KEY_TEMPLATE * template)2919 ifapi_key_create(
2920 FAPI_CONTEXT *context,
2921 IFAPI_KEY_TEMPLATE *template)
2922 {
2923 TSS2_RC r;
2924 size_t path_length;
2925 NODE_STR_T *path_list = context->loadKey.path_list;
2926 TPM2B_PUBLIC *outPublic = NULL;
2927 TPM2B_PRIVATE *outPrivate = NULL;
2928 TPM2B_CREATION_DATA *creationData = NULL;
2929 TPM2B_DIGEST *creationHash = NULL;
2930 TPMT_TK_CREATION *creationTicket = NULL;
2931 IFAPI_OBJECT *object = &context->cmd.Key_Create.object;
2932 ESYS_TR auth_session;
2933
2934 LOG_TRACE("call");
2935
2936 switch (context->cmd.Key_Create.state) {
2937 statecase(context->cmd.Key_Create.state, KEY_CREATE_INIT);
2938 context->cmd.Key_Create.public_templ = *template;
2939
2940 /* Profile name is first element of the explicit path list */
2941 char *profile_name = context->loadKey.path_list->str;
2942 r = ifapi_profiles_get(&context->profiles, profile_name, &context->cmd.Key_Create.profile);
2943 goto_if_error_reset_state(r, "Retrieving profile data", error_cleanup);
2944
2945 if (context->cmd.Key_Create.inSensitive.sensitive.data.size > 0) {
2946 /* A keyed hash object sealing sensitive data will be created */
2947 context->cmd.Key_Create.public_templ.public.publicArea.type = TPM2_ALG_KEYEDHASH;
2948 context->cmd.Key_Create.public_templ.public.publicArea.nameAlg =
2949 context->cmd.Key_Create.profile->nameAlg;
2950 context->cmd.Key_Create.public_templ.public.publicArea.parameters.keyedHashDetail.scheme.scheme =
2951 TPM2_ALG_NULL;
2952 } else {
2953 r = ifapi_merge_profile_into_template(context->cmd.Key_Create.profile,
2954 &context->cmd.Key_Create.public_templ);
2955 goto_if_error_reset_state(r, "Merge profile", error_cleanup);
2956 }
2957
2958 if (context->cmd.Key_Create.policyPath
2959 && strcmp(context->cmd.Key_Create.policyPath, "") != 0)
2960 context->cmd.Key_Create.state = KEY_CREATE_CALCULATE_POLICY;
2961 /* else jump over to KEY_CREATE_WAIT_FOR_SESSION below */
2962 /* FALLTHRU */
2963
2964 case KEY_CREATE_CALCULATE_POLICY:
2965 if (context->cmd.Key_Create.state == KEY_CREATE_CALCULATE_POLICY) {
2966 r = ifapi_calculate_tree(context, context->cmd.Key_Create.policyPath,
2967 &context->policy.policy,
2968 context->cmd.Key_Create.public_templ.public.publicArea.nameAlg,
2969 &context->policy.digest_idx,
2970 &context->policy.hash_size);
2971 return_try_again(r);
2972 goto_if_error2(r, "Calculate policy tree %s", error_cleanup,
2973 context->cmd.Key_Create.policyPath);
2974
2975 /* Store the calculated policy in the key object */
2976 object->policy = calloc(1, sizeof(TPMS_POLICY));
2977 return_if_null(object->policy, "Out of memory",
2978 TSS2_FAPI_RC_MEMORY);
2979 *(object->policy) = context->policy.policy;
2980
2981 context->cmd.Key_Create.public_templ.public.publicArea.authPolicy.size =
2982 context->policy.hash_size;
2983 memcpy(&context->cmd.Key_Create.public_templ.public.publicArea.authPolicy.buffer[0],
2984 &context->policy.policy.policyDigests.digests[context->policy.digest_idx].digest,
2985 context->policy.hash_size);
2986 }
2987 r = ifapi_get_sessions_async(context,
2988 IFAPI_SESSION_GENEK | IFAPI_SESSION1,
2989 TPMA_SESSION_DECRYPT, 0);
2990 goto_if_error_reset_state(r, "Create sessions", error_cleanup);
2991 fallthrough;
2992
2993 statecase(context->cmd.Key_Create.state, KEY_CREATE_WAIT_FOR_SESSION);
2994 LOG_TRACE("KEY_CREATE_WAIT_FOR_SESSION");
2995 r = ifapi_get_sessions_finish(context, context->cmd.Key_Create.profile,
2996 context->cmd.Key_Create.profile->nameAlg);
2997 return_try_again(r);
2998 goto_if_error_reset_state(r, " FAPI create session", error_cleanup);
2999
3000 path_length = ifapi_path_length(path_list);
3001 r = ifapi_load_key_async(context, path_length - 1);
3002 goto_if_error(r, "LoadKey async", error_cleanup);
3003 fallthrough;
3004
3005 statecase(context->cmd.Key_Create.state, KEY_CREATE_WAIT_FOR_PARENT);
3006 LOG_TRACE("KEY_CREATE_WAIT_FOR_PARENT");
3007 r = ifapi_load_key_finish(context, IFAPI_FLUSH_PARENT);
3008 return_try_again(r);
3009 goto_if_error(r, "LoadKey finish", error_cleanup);
3010 fallthrough;
3011
3012 statecase(context->cmd.Key_Create.state, KEY_CREATE_WAIT_FOR_AUTHORIZATION);
3013 r = ifapi_authorize_object(context, &context->loadKey.auth_object, &auth_session);
3014 FAPI_SYNC(r, "Authorize key.", error_cleanup);
3015
3016 r = Esys_Create_Async(context->esys, context->loadKey.auth_object.handle,
3017 auth_session,
3018 ESYS_TR_NONE, ESYS_TR_NONE,
3019 &context->cmd.Key_Create.inSensitive,
3020 &context->cmd.Key_Create.public_templ.public,
3021 &context->cmd.Key_Create.outsideInfo,
3022 &context->cmd.Key_Create.creationPCR);
3023 goto_if_error(r, "Create_Async", error_cleanup);
3024 fallthrough;
3025
3026 statecase(context->cmd.Key_Create.state, KEY_CREATE_AUTH_SENT);
3027 r = Esys_Create_Finish(context->esys, &outPrivate, &outPublic, &creationData,
3028 &creationHash, &creationTicket);
3029 try_again_or_error_goto(r, "Key create finish", error_cleanup);
3030
3031 /* Prepare object for serialization */
3032 object->system = context->cmd.Key_Create.public_templ.system;
3033 object->objectType = IFAPI_KEY_OBJ;
3034 object->misc.key.public = *outPublic;
3035 object->misc.key.private.size = outPrivate->size;
3036 object->misc.key.private.buffer = calloc(1, outPrivate->size);
3037 goto_if_null2( object->misc.key.private.buffer, "Out of memory.", r,
3038 TSS2_FAPI_RC_MEMORY, error_cleanup);
3039
3040 object->misc.key.private.buffer = memcpy(&object->misc.key.private.buffer[0],
3041 &outPrivate->buffer[0], outPrivate->size);
3042 object->misc.key.policyInstance = NULL;
3043 object->misc.key.creationData = *creationData;
3044 object->misc.key.creationTicket = *creationTicket;
3045 object->misc.key.description = NULL;
3046 object->misc.key.certificate = NULL;
3047 SAFE_FREE(outPrivate);
3048 SAFE_FREE(creationData);
3049 SAFE_FREE(creationTicket);
3050 SAFE_FREE(creationHash);
3051 if (context->cmd.Key_Create.inSensitive.sensitive.userAuth.size > 0)
3052 object->misc.key.with_auth = TPM2_YES;
3053 else
3054 object->misc.key.with_auth = TPM2_NO;;
3055 r = ifapi_get_name(&outPublic->publicArea, &object->misc.key.name);
3056 goto_if_error(r, "Get key name", error_cleanup);
3057
3058 if (object->misc.key.public.publicArea.type == TPM2_ALG_RSA)
3059 object->misc.key.signing_scheme = context->cmd.Key_Create.profile->rsa_signing_scheme;
3060 else
3061 object->misc.key.signing_scheme = context->cmd.Key_Create.profile->ecc_signing_scheme;
3062 SAFE_FREE(outPublic);
3063 fallthrough;
3064
3065 statecase(context->cmd.Key_Create.state, KEY_CREATE_WRITE_PREPARE);
3066 /* Perform esys serialization if necessary */
3067 r = ifapi_esys_serialize_object(context->esys, object);
3068 goto_if_error(r, "Prepare serialization", error_cleanup);
3069
3070 /* Start writing the NV object to the key store */
3071 r = ifapi_keystore_store_async(&context->keystore, &context->io,
3072 context->cmd.Key_Create.keyPath, object);
3073 goto_if_error_reset_state(r, "Could not open: %sh", error_cleanup,
3074 context->cmd.Key_Create.keyPath);
3075 ifapi_cleanup_ifapi_object(object);
3076 fallthrough;
3077
3078 statecase(context->cmd.Key_Create.state, KEY_CREATE_WRITE);
3079 /* Finish writing the key to the key store */
3080 r = ifapi_keystore_store_finish(&context->keystore, &context->io);
3081 return_try_again(r);
3082 return_if_error_reset_state(r, "write_finish failed");
3083
3084 if (context->loadKey.auth_object.misc.key.persistent_handle) {
3085 context->cmd.Key_Create.state = KEY_CREATE_INIT;
3086 r = TSS2_RC_SUCCESS;
3087 break;
3088 }
3089 /* Prepare Flushing of key used for authorization */
3090 r = Esys_FlushContext_Async(context->esys, context->loadKey.auth_object.handle);
3091 goto_if_error(r, "Flush parent", error_cleanup);
3092 fallthrough;
3093
3094 statecase(context->cmd.Key_Create.state, KEY_CREATE_FLUSH);
3095 r = Esys_FlushContext_Finish(context->esys);
3096 try_again_or_error_goto(r, "Flush context", error_cleanup);
3097 fallthrough;
3098
3099 statecase(context->cmd.Key_Create.state, KEY_CREATE_CLEANUP);
3100 r = ifapi_cleanup_session(context);
3101 try_again_or_error_goto(r, "Cleanup", error_cleanup);
3102
3103 context->cmd.Key_Create.state = KEY_CREATE_INIT;
3104 r = TSS2_RC_SUCCESS;
3105 break;
3106
3107 statecasedefault(context->cmd.Key_Create.state);
3108 }
3109 error_cleanup:
3110 free_string_list(context->loadKey.path_list);
3111 SAFE_FREE(outPublic);
3112 SAFE_FREE(outPrivate);
3113 SAFE_FREE(creationData);
3114 SAFE_FREE(creationHash);
3115 SAFE_FREE(creationTicket);
3116 SAFE_FREE(context->cmd.Key_Create.policyPath);
3117 SAFE_FREE(context->cmd.Key_Create.keyPath);
3118 ifapi_cleanup_ifapi_object(object);
3119 ifapi_session_clean(context);
3120 return r;
3121 }
3122
3123 /** Get signature scheme for key.
3124 *
3125 * If padding is passed the scheme will be derived from paddint otherwise
3126 * the scheme form object will be used.
3127 *
3128 * @param[in] context The FAPI_CONTEXT.
3129 * @param[in] object The internal FAPI object of the key.
3130 * @param[in] padding The strings RSA_SSA or RSA_PSS will be converted
3131 * into the TSS constants used for the signing scheme.
3132 * @param[in] digest The digest size will be used to determine the hashalg
3133 * for the signature scheme.
3134 * @param[out] sig_scheme The computed signature scheme.
3135 *
3136 * @retval TSS2_FAPI_RC_BAD_VALUE If the digest size is not appropriate.
3137 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
3138 */
3139 TSS2_RC
ifapi_get_sig_scheme(FAPI_CONTEXT * context,IFAPI_OBJECT * object,char const * padding,TPM2B_DIGEST * digest,TPMT_SIG_SCHEME * sig_scheme)3140 ifapi_get_sig_scheme(
3141 FAPI_CONTEXT *context,
3142 IFAPI_OBJECT *object,
3143 char const *padding,
3144 TPM2B_DIGEST *digest,
3145 TPMT_SIG_SCHEME *sig_scheme)
3146 {
3147 TPMI_ALG_HASH hash_alg;
3148 TSS2_RC r;
3149
3150 if (padding) {
3151 /* Get hash algorithm from digest size */
3152 r = ifapi_get_hash_alg_for_size(digest->size, &hash_alg);
3153 return_if_error2(r, "Invalid digest size.");
3154
3155 /* Use scheme object from context */
3156 if (strcasecmp("RSA_SSA", padding) == 0) {
3157 context->Key_Sign.scheme.scheme = TPM2_ALG_RSASSA;
3158 context->Key_Sign.scheme.details.rsassa.hashAlg = hash_alg;
3159 }
3160 if (strcasecmp("RSA_PSS", padding) == 0) {
3161 context->Key_Sign.scheme.scheme = TPM2_ALG_RSAPSS;
3162 context->Key_Sign.scheme.details.rsapss.hashAlg = hash_alg;
3163 }
3164 *sig_scheme = context->Key_Sign.scheme;
3165 return TSS2_RC_SUCCESS;
3166 } else {
3167 /* Use scheme defined for object */
3168 *sig_scheme = object->misc.key.signing_scheme;
3169 /* Get hash algorithm from digest size */
3170 r = ifapi_get_hash_alg_for_size(digest->size, &hash_alg);
3171 return_if_error2(r, "Invalid digest size.");
3172
3173 sig_scheme->details.any.hashAlg = hash_alg;
3174 return TSS2_RC_SUCCESS;
3175 }
3176 }
3177
3178 /** State machine for changing the hierarchy authorization.
3179 *
3180 * First it will be tried to set the auth value of the hierarchy with a
3181 * "null" authorization. If this trial is not successful it will be tried to
3182 * authorize the hierarchy via a callback.
3183 * If an not null auth value is passed with_auth is set to yes for the
3184 * object otherwise to no. So for later authorizations it will be clear
3185 * whether null authorization is possible or not.
3186 *
3187 * @param[in] context The FAPI_CONTEXT.
3188 * @param[in] handle The ESAPI handle of the hierarchy.
3189 * @param[in,out] hierarchy_object The internal FAPI representation of a
3190 * hierarchy.
3191 * @param[in] newAuthValue The new authorization for the hierarchy.
3192 *
3193 * @retval TSS2_RC_SUCCESS on success.
3194 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
3195 * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
3196 * this function needs to be called again.
3197 * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
3198 * operation already pending.
3199 * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback
3200 * is not set.
3201 */
3202 TSS2_RC
ifapi_change_auth_hierarchy(FAPI_CONTEXT * context,ESYS_TR handle,IFAPI_OBJECT * hierarchy_object,TPM2B_AUTH * newAuthValue)3203 ifapi_change_auth_hierarchy(
3204 FAPI_CONTEXT *context,
3205 ESYS_TR handle,
3206 IFAPI_OBJECT *hierarchy_object,
3207 TPM2B_AUTH *newAuthValue)
3208 {
3209 TSS2_RC r;
3210
3211 switch (context->hierarchy_state) {
3212 statecase(context->hierarchy_state, HIERARCHY_CHANGE_AUTH_INIT);
3213 if (newAuthValue->size > 0)
3214 hierarchy_object->misc.hierarchy.with_auth = TPM2_YES;
3215 else
3216 hierarchy_object->misc.hierarchy.with_auth = TPM2_NO;
3217 r = Esys_HierarchyChangeAuth_Async(context->esys,
3218 handle,
3219 (context->session1
3220 && context->session1 != ESYS_TR_NONE) ?
3221 context->session1 : ESYS_TR_PASSWORD,
3222 ESYS_TR_NONE, ESYS_TR_NONE,
3223 newAuthValue);
3224 return_if_error(r, "HierarchyChangeAuth");
3225 fallthrough;
3226
3227 statecase(context->hierarchy_state, HIERARCHY_CHANGE_AUTH_NULL_AUTH_SENT);
3228 r = Esys_HierarchyChangeAuth_Finish(context->esys);
3229 return_try_again(r);
3230
3231 if ((r & ~TPM2_RC_N_MASK) != TPM2_RC_BAD_AUTH) {
3232 return_if_error(r, "Hierarchy change auth.");
3233 context->hierarchy_state = HIERARCHY_CHANGE_AUTH_INIT;
3234 LOG_TRACE("success");
3235 return TSS2_RC_SUCCESS;
3236 }
3237
3238 /* Retry after NULL authorization was not successful */
3239 r = ifapi_set_auth(context, hierarchy_object, "Hierarchy object");
3240 return_if_error(r, "HierarchyChangeAuth");
3241
3242 r = Esys_HierarchyChangeAuth_Async(context->esys,
3243 handle,
3244 (context->session1
3245 && context->session1 != ESYS_TR_NONE) ?
3246 context->session1 : ESYS_TR_PASSWORD,
3247 ESYS_TR_NONE, ESYS_TR_NONE,
3248 newAuthValue);
3249 return_if_error(r, "HierarchyChangeAuth");
3250 fallthrough;
3251
3252 statecase(context->hierarchy_state, HIERARCHY_CHANGE_AUTH_AUTH_SENT);
3253 r = Esys_HierarchyChangeAuth_Finish(context->esys);
3254 FAPI_SYNC(r, "Hierarchy change auth.", error);
3255
3256 context->hierarchy_state = HIERARCHY_CHANGE_AUTH_INIT;
3257 return r;
3258
3259 statecasedefault(context->hierarchy_state);
3260 }
3261
3262 error:
3263 return r;
3264 }
3265
3266 /** State machine for changing the policy of a hierarchy.
3267 *
3268 * Based on a passed policy the policy digest will be computed.
3269 * First it will be tried to set the policy of the hierarchy with a
3270 * "null" authorization. If this trial is not successful it will be tried to
3271 * authorize the hierarchy via a callback.
3272 * If an not null auth value is passed with_auth is set to yes for the
3273 * object otherwise to no. So for later authorizations it will be clear
3274 * whether null authorization is possible or not.
3275 *
3276 * @param[in] context The FAPI_CONTEXT.
3277 * @param[in] handle The ESAPI handle of the hierarchy.
3278 * @param[in,out] hierarchy_object The internal FAPI representation of a
3279 * hierarchy.
3280 * @param[in] policy The new policy assigned to the hierarchy.
3281 *
3282 * @retval TSS2_RC_SUCCESS on success.
3283 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
3284 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
3285 * @retval TSS2_FAPI_RC_GENERAL_FAILURE If an internal error occurs, which is
3286 * not covered by other return codes.
3287 * @retval TSS2_FAPI_RC_BAD_VALUE If wrong values are detected during policy calculation.
3288 * @retval TSS2_FAPI_RC_IO_ERROR If an error occurs during access to the policy
3289 * store.
3290 * @retval TSS2_FAPI_RC_PATH_NOT_FOUND If an object needed for policy calculation was
3291 * not found.
3292 * @retval TSS2_FAPI_RC_POLICY_UNKNOWN If policy search for a certain policy digest was
3293 * not successful.
3294 * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
3295 * this function needs to be called again.
3296 * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
3297 * operation already pending.
3298 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
3299 * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
3300 * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback
3301 * is not set.
3302 */
3303 TSS2_RC
ifapi_change_policy_hierarchy(FAPI_CONTEXT * context,ESYS_TR handle,IFAPI_OBJECT * hierarchy_object,TPMS_POLICY * policy)3304 ifapi_change_policy_hierarchy(
3305 FAPI_CONTEXT *context,
3306 ESYS_TR handle,
3307 IFAPI_OBJECT *hierarchy_object,
3308 TPMS_POLICY *policy)
3309 {
3310 TSS2_RC r;
3311
3312 switch (context->hierarchy_policy_state) {
3313 statecase(context->hierarchy_policy_state, HIERARCHY_CHANGE_POLICY_INIT);
3314 if (! policy || ! policy->policy) {
3315 /* No policy will be used for hierarchy */
3316 return TSS2_RC_SUCCESS;
3317 }
3318
3319 context->policy.state = POLICY_INIT;
3320
3321 /* Calculate the policy digest which will be used as hierarchy policy. */
3322 r = ifapi_calculate_tree(context, NULL, /**< no path needed */
3323 policy,
3324 context->profiles.default_profile.nameAlg,
3325 &context->cmd.Provision.digest_idx,
3326 &context->cmd.Provision.hash_size);
3327 goto_if_error(r, "Policy calculation", error);
3328
3329
3330 /* Policy data will be stored in the provisioning context. */
3331 context->cmd.Provision.policy_digest.size = context->cmd.Provision.hash_size;
3332 memcpy(&context->cmd.Provision.policy_digest.buffer[0],
3333 &policy
3334 ->policyDigests.digests[context->cmd.Provision.digest_idx].digest,
3335 context->cmd.Provision.hash_size);
3336
3337 hierarchy_object->policy = policy;
3338 hierarchy_object->misc.hierarchy.authPolicy = context->cmd.Provision.policy_digest;
3339
3340 /* Prepare the setting of the policy. */
3341 r = Esys_SetPrimaryPolicy_Async(context->esys, handle,
3342 ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
3343 &context->cmd.Provision.policy_digest,
3344 context->profiles.default_profile.nameAlg);
3345 return_if_error(r, "Esys_SetPrimaryPolicy_Async");
3346 fallthrough;
3347
3348 statecase(context->hierarchy_policy_state, HIERARCHY_CHANGE_POLICY_NULL_AUTH_SENT);
3349 r = Esys_SetPrimaryPolicy_Finish(context->esys);
3350 return_try_again(r);
3351 if ((r & ~TPM2_RC_N_MASK) != TPM2_RC_BAD_AUTH) {
3352 return_if_error(r, "SetPrimaryPolicy_Finish");
3353 context->hierarchy_policy_state = HIERARCHY_CHANGE_POLICY_INIT;
3354 return TSS2_RC_SUCCESS;
3355 }
3356
3357 /* Retry after NULL authorization was not successful */
3358 ifapi_init_hierarchy_object(hierarchy_object, handle);
3359 r = ifapi_set_auth(context, hierarchy_object, "Hierarchy object");
3360 return_if_error(r, "HierarchyChangePolicy");
3361
3362 r = Esys_SetPrimaryPolicy_Async(context->esys, handle,
3363 context->session1, ESYS_TR_NONE, ESYS_TR_NONE,
3364 &context->cmd.Provision.policy_digest,
3365 context->profiles.default_profile.nameAlg);
3366 return_if_error(r, "Esys_SetPrimaryPolicy_Async");
3367
3368 fallthrough;
3369
3370 statecase(context->hierarchy_policy_state, HIERARCHY_CHANGE_POLICY_AUTH_SENT);
3371 r = Esys_SetPrimaryPolicy_Finish(context->esys);
3372 return_try_again(r);
3373 return_if_error(r, "SetPrimaryPolicy_Finish");
3374
3375 return TSS2_RC_SUCCESS;
3376
3377 statecasedefault(context->hierarchy_policy_state);
3378 }
3379
3380 error:
3381 return r;
3382 }
3383
3384 /** Allocate ifapi object and store the result in a linked list.
3385 *
3386 * Allocated ifapi objects will be recorded in the context.
3387 *
3388 * @param[in,out] context The FAPI_CONTEXT.
3389 *
3390 * @retval The allocated ifapi object.
3391 * @retval NULL if the object cannot be allocated.
3392 */
3393 IFAPI_OBJECT
ifapi_allocate_object(FAPI_CONTEXT * context)3394 *ifapi_allocate_object(FAPI_CONTEXT *context)
3395 {
3396 NODE_OBJECT_T *node = calloc(1, sizeof(NODE_OBJECT_T));
3397 if (!node)
3398 return NULL;
3399
3400 node->object = calloc(1, sizeof(IFAPI_OBJECT));
3401 if (!node->object) {
3402 free(node);
3403 return NULL;
3404 }
3405 node->next = context->object_list;
3406 context->object_list = node;
3407 return (IFAPI_OBJECT *) node->object;
3408 }
3409
3410 /** Free all ifapi objects stored in the context.
3411 *
3412 * @param[in,out] context The FAPI_CONTEXT.
3413 */
3414 void
ifapi_free_objects(FAPI_CONTEXT * context)3415 ifapi_free_objects(FAPI_CONTEXT *context)
3416 {
3417 NODE_OBJECT_T *free_node;
3418 NODE_OBJECT_T *node = context->object_list;
3419 while (node) {
3420 free(node->object);
3421 free_node = node;
3422 node = node->next;
3423 free(free_node);
3424 }
3425 }
3426
3427 /** Free ifapi a object stored in the context.
3428 *
3429 * @param[in,out] context The FAPI_CONTEXT.
3430 * @param[in,out] object The object which should be removed from the
3431 * the linked list stored in context.
3432 */
3433 void
ifapi_free_object(FAPI_CONTEXT * context,IFAPI_OBJECT ** object)3434 ifapi_free_object(FAPI_CONTEXT *context, IFAPI_OBJECT **object)
3435 {
3436 NODE_OBJECT_T *node;
3437 NODE_OBJECT_T **update_ptr;
3438
3439 for (node = context->object_list,
3440 update_ptr = &context->object_list;
3441 node != NULL;
3442 update_ptr = &node->next, node = node->next) {
3443 if (node->object == object) {
3444 *update_ptr = node->next;
3445 SAFE_FREE(node->object);
3446 SAFE_FREE(node);
3447 *object = NULL;
3448 return;
3449 }
3450 }
3451 }
3452
3453 #define ADD_CAPABILITY_INFO(capability, field, subfield, max_count, property_count) \
3454 if (context->cmd.GetInfo.fetched_data->data.capability.count > max_count - property_count) { \
3455 context->cmd.GetInfo.fetched_data->data.capability.count = max_count - property_count; \
3456 } \
3457 \
3458 memmove(&context->cmd.GetInfo.capability_data->data.capability.field[property_count], \
3459 context->cmd.GetInfo.fetched_data->data.capability.field, \
3460 context->cmd.GetInfo.fetched_data->data.capability.count \
3461 * sizeof(context->cmd.GetInfo.fetched_data->data.capability.field[0])); \
3462 property_count += context->cmd.GetInfo.fetched_data->data.capability.count; \
3463 \
3464 context->cmd.GetInfo.capability_data->data.capability.count = property_count; \
3465 \
3466 if (more_data && property_count < count \
3467 && context->cmd.GetInfo.fetched_data->data.capability.count) { \
3468 context->cmd.GetInfo.property \
3469 = context->cmd.GetInfo.capability_data->data. \
3470 capability.field[property_count - 1]subfield + 1; \
3471 } else { \
3472 more_data = false; \
3473 }
3474
3475
3476 /** Prepare the receiving of capability data.
3477 *
3478 * @param[in,out] context The FAPI_CONTEXT.
3479 *
3480 * @retval TSS2_RC_SUCCESS.
3481 */
3482 TPM2_RC
ifapi_capability_init(FAPI_CONTEXT * context)3483 ifapi_capability_init(FAPI_CONTEXT *context)
3484 {
3485 context->cmd.GetInfo.capability_data = NULL;
3486 context->cmd.GetInfo.fetched_data = NULL;
3487
3488 return TSS2_RC_SUCCESS;
3489
3490
3491 }
3492
3493 /** State machine for receiving TPM capability information.
3494 *
3495 * The state machine shares the state with the FAPI function Fapi_GetInfo.
3496 * context->state == GET_INFO_GET_CAP_MORE signals that more capability data can
3497 * be retrieved.
3498 *
3499 * @param[in,out] context The FAPI_CONTEXT.
3500 * @param[in] capability The capability to be retrieved.
3501 * @param[in] count The maximal number of items that should be retrieved.
3502 * @param[out] capability_data The retrieved capability information.
3503 *
3504 * @retval TSS2_RC_SUCCESS If all capability data is retrieved.
3505 * @retval TSS2_FAPI_RC_TRY_AGAIN if more capability data is available.
3506 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
3507 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
3508 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
3509 * the function.
3510 * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
3511 * operation already pending.
3512 */
3513 TPM2_RC
ifapi_capability_get(FAPI_CONTEXT * context,TPM2_CAP capability,UINT32 count,TPMS_CAPABILITY_DATA ** capability_data)3514 ifapi_capability_get(FAPI_CONTEXT *context, TPM2_CAP capability,
3515 UINT32 count, TPMS_CAPABILITY_DATA **capability_data) {
3516
3517 TPMI_YES_NO more_data;
3518 TSS2_RC r = TSS2_RC_SUCCESS;
3519 ESYS_CONTEXT *ectx = context->esys;
3520
3521 switch (context->state) {
3522 statecase(context->state, GET_INFO_GET_CAP);
3523 /* fetch capability info */
3524 context->cmd.GetInfo.fetched_data = NULL;
3525 context->cmd.GetInfo.capability_data = NULL;
3526 fallthrough;
3527
3528 statecase(context->state, GET_INFO_GET_CAP_MORE);
3529 r = Esys_GetCapability_Async(ectx, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
3530 capability, context->cmd.GetInfo.property,
3531 count - context->cmd.GetInfo.property_count);
3532 goto_if_error(r, "Error GetCapability", error_cleanup);
3533 fallthrough;
3534
3535 statecase(context->state, GET_INFO_WAIT_FOR_CAP);
3536 r = Esys_GetCapability_Finish(ectx, &more_data, &context->cmd.GetInfo.fetched_data);
3537 return_try_again(r);
3538 goto_if_error(r, "Error GetCapability", error_cleanup);
3539
3540 LOG_TRACE("GetCapability: capability: 0x%x, property: 0x%x", capability,
3541 context->cmd.GetInfo.property);
3542
3543 if (context->cmd.GetInfo.fetched_data->capability != capability) {
3544 goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
3545 "TPM returned different capability than requested: 0x%x != 0x%x",
3546 error_cleanup,
3547 context->cmd.GetInfo.fetched_data->capability, capability);
3548 }
3549
3550 if (context->cmd.GetInfo.capability_data == NULL) {
3551 /* reuse the TPM's result structure */
3552 context->cmd.GetInfo.capability_data = context->cmd.GetInfo.fetched_data;
3553
3554 if (!more_data) {
3555 /* there won't be another iteration of the loop, just return the result unmodified */
3556 *capability_data = context->cmd.GetInfo.capability_data;
3557 return TPM2_RC_SUCCESS;
3558 }
3559 }
3560
3561 /* append the TPM's results to the initial structure, as long as there is still space left */
3562 switch (capability) {
3563 case TPM2_CAP_ALGS:
3564 ADD_CAPABILITY_INFO(algorithms, algProperties, .alg,
3565 TPM2_MAX_CAP_ALGS,
3566 context->cmd.GetInfo.property_count);
3567 break;
3568 case TPM2_CAP_HANDLES:
3569 ADD_CAPABILITY_INFO(handles, handle,,
3570 TPM2_MAX_CAP_HANDLES,
3571 context->cmd.GetInfo.property_count);
3572 break;
3573 case TPM2_CAP_COMMANDS:
3574 ADD_CAPABILITY_INFO(command, commandAttributes,,
3575 TPM2_MAX_CAP_CC,
3576 context->cmd.GetInfo.property_count);
3577 /* workaround because tpm2-tss does not implement attribute commandIndex for TPMA_CC */
3578 context->cmd.GetInfo.property &= TPMA_CC_COMMANDINDEX_MASK;
3579 break;
3580 case TPM2_CAP_PP_COMMANDS:
3581 ADD_CAPABILITY_INFO(ppCommands, commandCodes,,
3582 TPM2_MAX_CAP_CC,
3583 context->cmd.GetInfo.property_count);
3584 break;
3585 case TPM2_CAP_AUDIT_COMMANDS:
3586 ADD_CAPABILITY_INFO(auditCommands, commandCodes,,
3587 TPM2_MAX_CAP_CC,
3588 context->cmd.GetInfo.property_count);
3589 break;
3590 case TPM2_CAP_PCRS:
3591 ADD_CAPABILITY_INFO(assignedPCR, pcrSelections, .hash,
3592 TPM2_NUM_PCR_BANKS,
3593 context->cmd.GetInfo.property_count);
3594 break;
3595 case TPM2_CAP_TPM_PROPERTIES:
3596 ADD_CAPABILITY_INFO(tpmProperties, tpmProperty, .property,
3597 TPM2_MAX_TPM_PROPERTIES,
3598 context->cmd.GetInfo.property_count);
3599 break;
3600 case TPM2_CAP_PCR_PROPERTIES:
3601 ADD_CAPABILITY_INFO(pcrProperties, pcrProperty, .tag,
3602 TPM2_MAX_PCR_PROPERTIES,
3603 context->cmd.GetInfo.property_count);
3604 break;
3605 case TPM2_CAP_ECC_CURVES:
3606 ADD_CAPABILITY_INFO(eccCurves, eccCurves,,
3607 TPM2_MAX_ECC_CURVES,
3608 context->cmd.GetInfo.property_count);
3609 break;
3610 case TPM2_CAP_VENDOR_PROPERTY:
3611 ADD_CAPABILITY_INFO(intelPttProperty, property,,
3612 TPM2_MAX_PTT_PROPERTIES,
3613 context->cmd.GetInfo.property_count);
3614 break;
3615 default:
3616 LOG_ERROR("Unsupported capability: 0x%x\n", capability);
3617 if (context->cmd.GetInfo.fetched_data != context->cmd.GetInfo.capability_data) {
3618 free(context->cmd.GetInfo.fetched_data);
3619 }
3620 free(context->cmd.GetInfo.capability_data);
3621 *capability_data = NULL;
3622 return TSS2_FAPI_RC_BAD_VALUE;
3623 }
3624
3625 if (context->cmd.GetInfo.fetched_data != context->cmd.GetInfo.capability_data) {
3626 free(context->cmd.GetInfo.fetched_data);
3627 }
3628 *capability_data = context->cmd.GetInfo.capability_data;
3629 break;
3630
3631 statecasedefault(context->state);
3632 }
3633 if (more_data) {
3634 context->state = GET_INFO_GET_CAP_MORE;
3635 return TSS2_FAPI_RC_TRY_AGAIN;
3636 } else {
3637 context->state = _FAPI_STATE_INIT;
3638 return TSS2_RC_SUCCESS;
3639 }
3640
3641 error_cleanup:
3642 context->state = _FAPI_STATE_INIT;
3643 SAFE_FREE(context->cmd.GetInfo.capability_data);
3644 SAFE_FREE(context->cmd.GetInfo.fetched_data);
3645 return r;
3646 }
3647
3648 /** Get certificates stored in NV ram.
3649 *
3650 * The NV handles in the certificate range are determined. The corresponding
3651 * certificates are read out and stored in a linked list.
3652 *
3653 * @param[in,out] context The FAPI_CONTEXT. The sub context for NV reading
3654 * will be used.
3655 * @param[in] min_handle The first possible handle in the handle range.
3656 * @param[in] max_handle Maximal handle to filter out the handles not in the
3657 * handle range for certificates.
3658 * @param[out] cert_list The callee allocates linked list of certificates.
3659 *
3660 * @retval TSS2_RC_SUCCESS on success.
3661 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
3662 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
3663 *
3664 * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
3665 * this function needs to be called again.
3666 * @retval TSS2_FAPI_RC_BAD_SEQUENCE if the context has an asynchronous
3667 * operation already pending.
3668 * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback
3669 * is not set.
3670 * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
3671 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
3672 * @retval TSS2_FAPI_RC_IO_ERROR if an error occurred while accessing the
3673 * object store.
3674 * @retval TSS2_FAPI_RC_POLICY_UNKNOWN if policy search for a certain policy digest
3675 * was not successful.
3676 */
3677 TSS2_RC
ifapi_get_certificates(FAPI_CONTEXT * context,UINT32 min_handle,UINT32 max_handle,NODE_OBJECT_T ** cert_list)3678 ifapi_get_certificates(
3679 FAPI_CONTEXT *context,
3680 UINT32 min_handle,
3681 UINT32 max_handle,
3682 NODE_OBJECT_T **cert_list)
3683 {
3684 TSS2_RC r;
3685 TPMI_YES_NO moreData;
3686 TPMS_CAPABILITY_DATA **capabilityData = &context->cmd.Provision.capabilityData;
3687 TPM2B_NV_PUBLIC *nvPublic;
3688 uint8_t *cert_data;
3689 size_t cert_size;
3690
3691 context->cmd.Provision.cert_nv_idx = MIN_EK_CERT_HANDLE;
3692 context->cmd.Provision.capabilityData = NULL;
3693
3694 switch (context->get_cert_state) {
3695 statecase(context->get_cert_state, GET_CERT_INIT);
3696 *cert_list = NULL;
3697 context->cmd.Provision.cert_idx = 0;
3698 /* Prepare the reading of the capability handles in the certificate range */
3699 r = Esys_GetCapability_Async(context->esys,
3700 ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
3701 TPM2_CAP_HANDLES, min_handle,
3702 TPM2_MAX_CAP_HANDLES);
3703 goto_if_error(r, "Esys_GetCapability_Async", error);
3704 fallthrough;
3705
3706 statecase(context->get_cert_state, GET_CERT_WAIT_FOR_GET_CAP);
3707 r = Esys_GetCapability_Finish(context->esys, &moreData, capabilityData);
3708 return_try_again(r);
3709 goto_if_error_reset_state(r, "GetCapablity_Finish", error);
3710
3711 if (!*capabilityData || (*capabilityData)->data.handles.count == 0) {
3712 *cert_list = NULL;
3713 return TSS2_RC_SUCCESS;
3714 }
3715 context->cmd.Provision.capabilityData = *capabilityData;
3716 context->cmd.Provision.cert_count = (*capabilityData)->data.handles.count;
3717
3718 /* Filter out NV handles beyond the EK cert range */
3719 for (size_t i = 0; i < context->cmd.Provision.cert_count; i++) {
3720 if (context->cmd.Provision.capabilityData->data.handles.handle[i] > max_handle) {
3721 context->cmd.Provision.cert_count = i;
3722 break;
3723 }
3724 }
3725 fallthrough;
3726
3727 statecase(context->get_cert_state, GET_CERT_GET_CERT_NV);
3728 goto_if_null(context->cmd.Provision.capabilityData,
3729 "capabilityData is null", TSS2_FAPI_RC_MEMORY, error);
3730 context->cmd.Provision.cert_nv_idx
3731 = context->cmd.Provision.capabilityData
3732 ->data.handles.handle[context->cmd.Provision.cert_idx];
3733
3734 ifapi_init_hierarchy_object(&context->nv_cmd.auth_object,
3735 TPM2_RH_OWNER);
3736
3737 r = Esys_TR_FromTPMPublic_Async(context->esys,
3738 context->cmd.Provision.cert_nv_idx,
3739 ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE);
3740 goto_if_error_reset_state(r, "Esys_TR_FromTPMPublic_Async", error);
3741 fallthrough;
3742
3743 statecase(context->get_cert_state, GET_CERT_GET_CERT_NV_FINISH);
3744 r = Esys_TR_FromTPMPublic_Finish(context->esys,
3745 &context->cmd.Provision.esys_nv_cert_handle);
3746 return_try_again(r);
3747 goto_if_error_reset_state(r, "TR_FromTPMPublic_Finish", error);
3748
3749 /* Read public to get size of certificate */
3750 r = Esys_NV_ReadPublic_Async(context->esys,
3751 context->cmd.Provision.esys_nv_cert_handle,
3752 ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE);
3753 goto_if_error_reset_state(r, "Esys_NV_ReadPublic_Async", error);
3754 fallthrough;
3755
3756 statecase(context->get_cert_state, GET_CERT_GET_CERT_READ_PUBLIC);
3757 r = Esys_NV_ReadPublic_Finish(context->esys,
3758 &nvPublic,
3759 NULL);
3760 return_try_again(r);
3761 goto_if_error(r, "Error: nv read public", error);
3762
3763 /* TPMA_NV_NO_DA is set for NV certificate */
3764 context->nv_cmd.nv_object.misc.nv.public.nvPublic.attributes = TPMA_NV_NO_DA;
3765
3766 /* Prepare context for nv read */
3767 context->nv_cmd.data_idx = 0;
3768 context->nv_cmd.auth_index = ESYS_TR_RH_OWNER;
3769 context->nv_cmd.numBytes = nvPublic->nvPublic.dataSize;
3770 context->nv_cmd.esys_handle = context->cmd.Provision.esys_nv_cert_handle;
3771 context->nv_cmd.offset = 0;
3772 context->cmd.Provision.pem_cert = NULL;
3773 context->session1 = ESYS_TR_PASSWORD;
3774 context->session2 = ESYS_TR_NONE;
3775 context->nv_cmd.nv_read_state = NV_READ_INIT;
3776 memset(&context->nv_cmd.nv_object, 0, sizeof(IFAPI_OBJECT));
3777 Esys_Free(nvPublic);
3778 fallthrough;
3779
3780 statecase(context->get_cert_state, GET_CERT_READ_CERT);
3781 r = ifapi_nv_read(context, &cert_data, &cert_size);
3782 return_try_again(r);
3783 goto_if_error_reset_state(r, " FAPI NV_Read", error);
3784
3785 context->cmd.Provision.cert_idx += 1;
3786
3787 /* Add cert to list */
3788 if (context->cmd.Provision.cert_idx == context->cmd.Provision.cert_count) {
3789 context->get_cert_state = GET_CERT_GET_CERT_NV;
3790
3791 r = push_object_with_size_to_list(cert_data, cert_size, cert_list);
3792 goto_if_error(r, "Store certificate in list.", error);
3793
3794 return TSS2_RC_SUCCESS;
3795 } else {
3796 context->get_cert_state = GET_CERT_GET_CERT_NV;
3797 }
3798 break;
3799
3800 statecasedefault(context->get_cert_state);
3801 }
3802
3803 error:
3804 ifapi_free_object_list(*cert_list);
3805 return r;
3806 }
3807
3808
3809 /** Get description of an internal FAPI object.
3810 *
3811 * @param[in] object The object with the description.
3812 * @param[out] description The callee allocated description.
3813 *
3814 * @retval TSS2_RC_SUCCESS If a copy of the description can be returned
3815 * or if no description exists.
3816 * @retval TSS2_FAPI_RC_MEMORY in the copy cannot be allocated.
3817 */
3818 TSS2_RC
ifapi_get_description(IFAPI_OBJECT * object,char ** description)3819 ifapi_get_description(IFAPI_OBJECT *object, char **description)
3820 {
3821 char *obj_description = NULL;
3822
3823 switch (object->objectType) {
3824 case IFAPI_KEY_OBJ:
3825 obj_description = object->misc.key.description;
3826 break;
3827 case IFAPI_NV_OBJ:
3828 obj_description = object->misc.nv.description;
3829 break;
3830 case IFAPI_HIERARCHY_OBJ:
3831 obj_description = object->misc.hierarchy.description;
3832 break;
3833 default:
3834 *description = NULL;
3835 return TSS2_RC_SUCCESS;
3836 }
3837 if (obj_description) {
3838 *description = strdup(obj_description);
3839 check_oom(*description);
3840 } else {
3841 *description = NULL;
3842 }
3843 return TSS2_RC_SUCCESS;
3844 }
3845
3846 /** Set description of an internal FAPI object.
3847 *
3848 * @param[in,out] object The object with the description.
3849 * @param[in] description The description char strint or NULL.
3850 */
3851 void
ifapi_set_description(IFAPI_OBJECT * object,char * description)3852 ifapi_set_description(IFAPI_OBJECT *object, char *description)
3853 {
3854 switch (object->objectType) {
3855 case IFAPI_KEY_OBJ:
3856 SAFE_FREE(object->misc.key.description);
3857 object->misc.key.description = description;
3858 break;
3859 case IFAPI_NV_OBJ:
3860 SAFE_FREE(object->misc.nv.description);
3861 object->misc.nv.description = description;
3862 break;
3863 case IFAPI_HIERARCHY_OBJ:
3864 SAFE_FREE(object->misc.hierarchy.description);
3865 object->misc.hierarchy.description = description;
3866 break;
3867 default:
3868 LOG_WARNING("Description can't be set");
3869 break;
3870 }
3871 }
3872