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 <stdlib.h>
12 #include <errno.h>
13 #include <unistd.h>
14 #include <errno.h>
15 #include <string.h>
16
17 #include "fapi_util.h"
18 #include "tss2_tcti.h"
19 #include "tss2_esys.h"
20 #include "tss2_fapi.h"
21 #include "fapi_int.h"
22 #include "fapi_crypto.h"
23 #include "fapi_policy.h"
24 #include "ifapi_get_intl_cert.h"
25
26 #define LOGMODULE fapi
27 #include "util/log.h"
28 #include "util/aux_util.h"
29
30 #define EK_CERT_RANGE (0x01c07fff)
31
32 /** One-Call function for the initial FAPI provisioning.
33 *
34 * Provisions a TSS with its TPM. This includes the setting of important passwords
35 * and policy settings as well as the readout of the EK and its certificate and
36 * the initialization of the system-wide keystore.
37 *
38 * @param[in,out] context The FAPI_CONTEXT.
39 * @param[in] authValueEh The authorization value for the endorsement
40 * hierarchy. May be NULL
41 * @param[in] authValueSh The authorization value for the storage hierarchy.
42 * Should be NULL
43 * @param[in] authValueLockout The authorization value for lockout.
44 *
45 * @retval TSS2_RC_SUCCESS: if the function call was a success.
46 * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
47 * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
48 * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
49 * operation already pending.
50 * @retval TSS2_FAPI_RC_NO_CERT: if no certificate was found for the computed EK.
51 * @retval TSS2_FAPI_RC_BAD_KEY: if public key of the EK does not match the
52 * configured certificate or the configured fingerprint does not match
53 * the computed EK.
54 * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
55 * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
56 * internal operations or return parameters.
57 * @retval TSS2_FAPI_RC_NO_TPM if FAPI was initialized in no-TPM-mode via its
58 * config file.
59 * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
60 * this function needs to be called again.
61 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
62 * the function.
63 * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback
64 * is not set.
65 * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
66 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
67 * @retval TSS2_FAPI_RC_POLICY_UNKNOWN if policy search for a certain policy digest
68 * was not successful.
69 * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found
70 * during authorization.
71 * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
72 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
73 */
74 TSS2_RC
Fapi_Provision(FAPI_CONTEXT * context,char const * authValueEh,char const * authValueSh,char const * authValueLockout)75 Fapi_Provision(
76 FAPI_CONTEXT *context,
77 char const *authValueEh,
78 char const *authValueSh,
79 char const *authValueLockout)
80 {
81 LOG_TRACE("called for context:%p", context);
82
83 TSS2_RC r, r2;
84
85 /* Check for NULL parameters */
86 check_not_null(context);
87
88 /* Check whether TCTI and ESYS are initialized */
89 return_if_null(context->esys, "Command can't be executed in none TPM mode.",
90 TSS2_FAPI_RC_NO_TPM);
91
92 /* If the async state automata of FAPI shall be tested, then we must not set
93 the timeouts of ESYS to blocking mode.
94 During testing, the mssim tcti will ensure multiple re-invocations.
95 Usually however the synchronous invocations of FAPI shall instruct ESYS
96 to block until a result is available. */
97 #ifndef TEST_FAPI_ASYNC
98 r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
99 return_if_error_reset_state(r, "Set Timeout to blocking");
100 #endif /* TEST_FAPI_ASYNC */
101
102 r = Fapi_Provision_Async(context, authValueEh, authValueSh, authValueLockout);
103 return_if_error_reset_state(r, "Provision");
104
105 do {
106 /* We wait for file I/O to be ready if the FAPI state automata
107 are in a file I/O state. */
108 r = ifapi_io_poll(&context->io);
109 return_if_error(r, "Something went wrong with IO polling");
110
111 /* Repeatedly call the finish function, until FAPI has transitioned
112 through all execution stages / states of this invocation. */
113 r = Fapi_Provision_Finish(context);
114 } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
115
116 /* Reset the ESYS timeout to non-blocking, immediate response. */
117 r2 = Esys_SetTimeout(context->esys, 0);
118 return_if_error(r2, "Set Timeout to non-blocking");
119
120 return_if_error_reset_state(r, "Provision");
121
122 LOG_TRACE("finished");
123 return TSS2_RC_SUCCESS;
124 }
125
126 /** Asynchronous function for the initial FAPI provisioning.
127 *
128 * Provisions a TSS with its TPM. This includes the setting of important passwords
129 * and policy settings as well as the readout of the EK and its certificate and
130 * the initialization of the system-wide keystore.
131 *
132 * Call Fapi_Provision_Finish to finish the execution of this command.
133 *
134 * @param[in,out] context The FAPI_CONTEXT.
135 * @param[in] authValueEh The authorization value for the endorsement
136 * hierarchy. May be NULL
137 * @param[in] authValueSh The authorization value for the storage hierarchy.
138 * Should be NULL
139 * @param[in] authValueLockout The authorization value for lockout.
140 *
141 * @retval TSS2_RC_SUCCESS: if the function call was a success.
142 * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
143 * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
144 * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
145 * operation already pending.
146 * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
147 * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
148 * internal operations or return parameters.
149 * @retval TSS2_FAPI_RC_NO_TPM if FAPI was initialized in no-TPM-mode via its
150 * config file.
151 */
152 TSS2_RC
Fapi_Provision_Async(FAPI_CONTEXT * context,char const * authValueEh,char const * authValueSh,char const * authValueLockout)153 Fapi_Provision_Async(
154 FAPI_CONTEXT *context,
155 char const *authValueEh,
156 char const *authValueSh,
157 char const *authValueLockout)
158 {
159 LOG_TRACE("called for context:%p", context);
160 LOG_TRACE("authValueEh: %s", authValueEh);
161 LOG_TRACE("authValueSh: %s", authValueSh);
162 LOG_TRACE("authValueLockout: %s", authValueLockout);
163
164 TSS2_RC r;
165
166 /* Check for NULL parameters */
167 check_not_null(context);
168
169 /* Helpful alias pointers */
170 IFAPI_Provision * command = &context->cmd.Provision;
171
172 r = ifapi_session_init(context);
173 goto_if_error(r, "Initialize Provision", end);
174
175 /* Initialize context and duplicate parameters */
176 strdup_check(command->authValueLockout, authValueLockout, r, end);
177 strdup_check(command->authValueEh, authValueEh, r, end);
178 strdup_check(command->authValueSh, authValueSh, r, end);
179 context->ek_handle = ESYS_TR_NONE;
180 context->srk_handle = ESYS_TR_NONE;
181 command->cert_nv_idx = MIN_EK_CERT_HANDLE;
182 command->capabilityData = NULL;
183
184 /* Set the initial state for the finish method. */
185 context->state = PROVISION_READ_PROFILE;
186 LOG_TRACE("finished");
187 return TSS2_RC_SUCCESS;
188 end:
189 SAFE_FREE(command->authValueLockout);
190 SAFE_FREE(command->authValueEh);
191 SAFE_FREE(command->authValueSh);
192 return r;
193 }
194
195 /** Asynchronous finish function for Fapi_Provision
196 *
197 * This function should be called after a previous Fapi_Provision_Async.
198 *
199 * @param[in,out] context The FAPI_CONTEXT
200 *
201 * @retval TSS2_RC_SUCCESS: if the function call was a success.
202 * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
203 * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
204 * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
205 * operation already pending.
206 * @retval TSS2_FAPI_RC_NO_CERT: if no certificate was found for the computed EK.
207 * @retval TSS2_FAPI_RC_BAD_KEY: if public key of the EK does not match the
208 * configured certificate or the configured fingerprint does not match
209 * the computed EK.
210 * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
211 * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
212 * internal operations or return parameters.
213 * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
214 * complete. Call this function again later.
215 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
216 * the function.
217 * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback
218 * is not set.
219 * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
220 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
221 * @retval TSS2_FAPI_RC_POLICY_UNKNOWN if policy search for a certain policy digest
222 * was not successful.
223 * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if a FAPI object path was not found
224 * during authorization.
225 * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if a key was not found.
226 * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
227 */
228 TSS2_RC
Fapi_Provision_Finish(FAPI_CONTEXT * context)229 Fapi_Provision_Finish(FAPI_CONTEXT *context)
230 {
231 LOG_TRACE("called for context:%p", context);
232
233 TSS2_RC r = TSS2_RC_SUCCESS;
234 TPM2B_NV_PUBLIC *nvPublic = NULL;
235 uint8_t *certData = NULL;
236 size_t certSize;
237 TPMI_YES_NO moreData;
238 size_t hash_size;
239 TPMI_ALG_HASH hash_alg;
240 TPM2B_DIGEST ek_fingerprint;
241
242 /* Check for NULL parameters */
243 check_not_null(context);
244
245 /* Helpful alias pointers */
246 IFAPI_Provision * command = &context->cmd.Provision;
247 IFAPI_OBJECT *hierarchy = &command->hierarchy;
248 TPMS_CAPABILITY_DATA **capabilityData = &command->capabilityData;
249 IFAPI_NV_Cmds * nvCmd = &context->nv_cmd;
250 IFAPI_OBJECT * pkeyObject = &context->createPrimary.pkey_object;
251 IFAPI_KEY * pkey = &pkeyObject->misc.key;
252 IFAPI_PROFILE * defaultProfile = &context->profiles.default_profile;
253 int curl_rc;
254
255 switch (context->state) {
256 statecase(context->state, PROVISION_READ_PROFILE);
257 /*
258 * The default values used for profiling will be used from
259 * the default profile.
260 */
261 command->root_crt = NULL;
262
263 /* Generate template for SRK creation. */
264 r = ifapi_set_key_flags(defaultProfile->srk_template,
265 context->profiles.default_profile.srk_policy ? true : false,
266 &command->public_templ);
267 goto_if_error(r, "Set key flags for SRK", error_cleanup);
268
269 r = ifapi_merge_profile_into_template(&context->profiles.default_profile,
270 &command->public_templ);
271 goto_if_error(r, "Merging profile and template", error_cleanup);
272
273 /* Prepare the setting of the dictionary attack parameters. */
274 r = Esys_DictionaryAttackParameters_Async(context->esys, ESYS_TR_RH_LOCKOUT,
275 ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
276 defaultProfile->newMaxTries, defaultProfile->newRecoveryTime,
277 defaultProfile->lockoutRecovery);
278 goto_if_error(r, "Error Esys_DictionaryAttackParameters",
279 error_cleanup);
280 fallthrough;
281
282 statecase(context->state, PROVISION_WRITE_LOCKOUT_PARAM);
283 r = Esys_DictionaryAttackParameters_Finish(context->esys);
284 return_try_again(r);
285 goto_if_error_reset_state(r, "DictionaryAttackParameters_Finish",
286 error_cleanup);
287
288 /* Prepare the command for reading the TPMs PCR capabilities. */
289 r = Esys_GetCapability_Async(context->esys,
290 ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, TPM2_CAP_PCRS, 0, 1);
291 goto_if_error(r, "Esys_GetCapability_Async", error_cleanup);
292
293 fallthrough;
294
295 statecase(context->state, PROVISION_WAIT_FOR_GET_CAP1);
296 r = Esys_GetCapability_Finish(context->esys, &moreData, capabilityData);
297 return_try_again(r);
298 goto_if_error_reset_state(r, "GetCapablity_Finish", error_cleanup);
299
300 /* Check whether the TPMs PCR capabilities are compatible with the profile. */
301 TPML_PCR_SELECTION pcr_capability = (*capabilityData)->data.assignedPCR;
302 r = ifapi_check_profile_pcr_selection(&defaultProfile->pcr_selection,
303 &pcr_capability);
304 goto_if_error(r, "Invalid PCR selection in profile.", error_cleanup);
305
306 SAFE_FREE(*capabilityData);
307 fallthrough;
308
309 statecase(context->state, PROVISION_INIT_SRK);
310 /* Clear key object for the primary to be created */
311 memset(pkey, 0, sizeof(IFAPI_KEY));
312
313 /* Prepare the SRK generation. */
314 r = ifapi_init_primary_async(context, TSS2_SRK);
315 goto_if_error(r, "Initialize primary", error_cleanup);
316
317 context->state = PROVISION_AUTH_SRK_NO_AUTH_SENT;
318 fallthrough;
319
320 statecase(context->state, PROVISION_AUTH_SRK_AUTH_SENT);
321 fallthrough;
322
323 statecase(context->state, PROVISION_AUTH_SRK_NO_AUTH_SENT);
324 r = ifapi_init_primary_finish(context, TSS2_SRK);
325 return_try_again(r);
326 goto_if_error(r, "Init primary finish.", error_cleanup);
327
328 /* Check whether a persistent SRK handle was defined in profile. */
329 if (command->public_templ.persistent_handle) {
330 /* Assign found handle to object */
331 pkey->persistent_handle = command->public_templ.persistent_handle;
332
333 /* Initialize hierarchy object used for evict control. */
334 ifapi_init_hierarchy_object(hierarchy, ESYS_TR_RH_OWNER);
335
336 /* Prepare making the SRK permanent. */
337 r = Esys_EvictControl_Async(context->esys, hierarchy->handle,
338 pkeyObject->handle, ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
339 pkey->persistent_handle);
340 goto_if_error(r, "Error Esys EvictControl", error_cleanup);
341
342 context->state = PROVISION_WAIT_FOR_SRK_PERSISTENT;
343 return TSS2_FAPI_RC_TRY_AGAIN;
344 }
345 /* No further ESYS command is needed, the keystore object can be written. */
346 context->state = PROVISION_SRK_WRITE_PREPARE;
347 fallthrough;
348
349 statecase(context->state, PROVISION_SRK_WRITE_PREPARE);
350 pkeyObject->objectType = IFAPI_KEY_OBJ;
351 pkeyObject->system = command->public_templ.system;
352
353 /* Perform esys serialization if necessary */
354 r = ifapi_esys_serialize_object(context->esys, pkeyObject);
355 goto_if_error(r, "Prepare serialization", error_cleanup);
356
357 /* Start writing the SRK to the key store */
358 r = ifapi_keystore_store_async(&context->keystore, &context->io, "HS/SRK",
359 pkeyObject);
360 goto_if_error_reset_state(r, "Could not open: %sh", error_cleanup, "HS/SRK");
361 context->state = PROVISION_SRK_WRITE;
362 fallthrough;
363
364 statecase(context->state, PROVISION_SRK_WRITE);
365 /* Finish writing the SRK to the key store */
366 r = ifapi_keystore_store_finish(&context->keystore, &context->io);
367 return_try_again(r);
368 goto_if_error_reset_state(r, "write_finish failed", error_cleanup);
369
370 /* Clean objects used for SRK computation */
371 ifapi_cleanup_ifapi_object(pkeyObject);
372 memset(&command->public_templ, 0, sizeof(IFAPI_KEY_TEMPLATE));
373
374 /* Generate template for EK creation. */
375 r = ifapi_set_key_flags(defaultProfile->ek_template,
376 context->profiles.default_profile.ek_policy ? true : false,
377 &command->public_templ);
378 goto_if_error(r, "Set key flags for SRK", error_cleanup);
379
380 r = ifapi_merge_profile_into_template(&context->profiles.default_profile,
381 &command->public_templ);
382 goto_if_error(r, "Merging profile", error_cleanup);
383
384 /* Clear key object for the primary to be created */
385 memset(pkey, 0, sizeof(IFAPI_KEY));
386
387 /* Prepare the EK generation. */
388 r = ifapi_init_primary_async(context, TSS2_EK);
389 goto_if_error(r, "Initialize primary", error_cleanup);
390 fallthrough;
391 statecase(context->state, PROVISION_AUTH_EK_AUTH_SENT);
392 fallthrough;
393
394 statecase(context->state, PROVISION_AUTH_EK_NO_AUTH_SENT);
395 r = ifapi_init_primary_finish(context, TSS2_EK);
396 return_try_again(r);
397 goto_if_error(r, "Init primary finish", error_cleanup);
398
399 /* Check whether a persistent EK handle was defined in profile. */
400 if (command->public_templ.persistent_handle) {
401
402 /* Initialize hierarchy object used for EK processing. */
403 ifapi_init_hierarchy_object(hierarchy, ESYS_TR_RH_OWNER);
404
405 pkey->persistent_handle = command->public_templ.persistent_handle;
406
407 /* Prepare making the EK permanent. */
408 r = Esys_EvictControl_Async(context->esys, hierarchy->handle,
409 pkeyObject->handle, ESYS_TR_PASSWORD, ESYS_TR_NONE,
410 ESYS_TR_NONE, pkey->persistent_handle);
411 goto_if_error(r, "Error Esys EvictControl", error_cleanup);
412 context->state = PROVISION_WAIT_FOR_EK_PERSISTENT;
413 return TSS2_FAPI_RC_TRY_AGAIN;
414 }
415 fallthrough;
416
417 statecase(context->state, PROVISION_INIT_GET_CAP2);
418 if (context->config.ek_cert_less == TPM2_YES) {
419 /* Skip certificate validation. */
420 context->state = PROVISION_EK_WRITE_PREPARE;
421 return TSS2_FAPI_RC_TRY_AGAIN;
422 }
423
424 /* Check whether fingerprint for EK is defined in config file. */
425 hash_alg = context->config.ek_fingerprint.hashAlg;
426 if (hash_alg) {
427 LOG_DEBUG("Only fingerprint check for EK.");
428 if (!(hash_size =ifapi_hash_get_digest_size(hash_alg))) {
429 goto_error(r, TSS2_ESYS_RC_NOT_IMPLEMENTED,
430 "Unsupported hash algorithm (%" PRIu16 ")", error_cleanup,
431 hash_alg);
432 }
433 r = ifapi_get_tpm_key_fingerprint(&pkeyObject->misc.key.public, hash_alg,
434 &ek_fingerprint);
435 goto_if_error_reset_state(r, "Get fingerprint of EK", error_cleanup);
436
437 if (hash_size != ek_fingerprint.size ||
438 memcmp(&context->config.ek_fingerprint.digest, &ek_fingerprint.buffer[0],
439 hash_size) != 0) {
440 goto_error(r, TSS2_FAPI_RC_BAD_KEY,
441 "Fingerprint of EK not equal to fingerprint in config file.",
442 error_cleanup);
443 }
444 /* The fingerprint was found no further certificate processing needed. */
445 context->state = PROVISION_EK_WRITE_PREPARE;
446 return TSS2_FAPI_RC_TRY_AGAIN;
447 }
448
449 /* Check whether EK certificate has to be retrieved */
450 if (context->config.ek_cert_file) {
451 size_t cert_size;
452 TPM2B_PUBLIC public_key;
453
454 /* Curl will be used to retrieve the certificate from a file or via HTTP. */
455 curl_rc = ifapi_get_curl_buffer((unsigned char *)context->config.ek_cert_file,
456 (unsigned char **)&command->pem_cert, &cert_size);
457 if (curl_rc != 0) {
458 goto_error_reset_state(r, TSS2_FAPI_RC_NO_CERT, "Get certificate.",
459 error_cleanup);
460 }
461
462 /* Get the public key from the certificate. */
463 r = ifapi_get_public_from_pem_cert(command->pem_cert, &public_key);
464 goto_if_error_reset_state(r, "Get public key from pem certificate",
465 error_cleanup);
466 /* Compare public key of certificate with public data of EK */
467 if (ifapi_cmp_public_key(&pkeyObject->misc.key.public, &public_key)) {
468 /* The retrieved certificate will be written to keystore,
469 no further certificate processing needed. */
470 context->state = PROVISION_EK_WRITE_PREPARE;
471 return TSS2_FAPI_RC_TRY_AGAIN;
472 }
473 goto_error(r, TSS2_FAPI_RC_BAD_KEY,
474 "Public key of EK does not match certificate.",
475 error_cleanup);
476 }
477
478 /* Prepare the search for certificates store in the NV ram of the TPM. */
479 r = Esys_GetCapability_Async(context->esys,
480 ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, TPM2_CAP_HANDLES,
481 MIN_EK_CERT_HANDLE, TPM2_MAX_CAP_HANDLES);
482 goto_if_error(r, "Esys_GetCapability_Async", error_cleanup);
483
484 fallthrough;
485
486 statecase(context->state, PROVISION_WAIT_FOR_GET_CAP2);
487 r = Esys_GetCapability_Finish(context->esys, &moreData, capabilityData);
488 return_try_again(r);
489 goto_if_error_reset_state(r, "GetCapablity_Finish", error_cleanup);
490
491 if ((*capabilityData)->data.handles.count == 0) {
492 /* No more certificate, the EK can be compared with the certificates. */
493 Esys_Free(*capabilityData);
494 context->state = PROVISION_CHECK_FOR_VENDOR_CERT;
495 return TSS2_FAPI_RC_TRY_AGAIN;
496 }
497 command->capabilityData = *capabilityData;
498 command->cert_count = (*capabilityData)->data.handles.count;
499
500 /* Filter out NV handles beyond the EK cert range */
501 for (size_t i = 0; i < command->cert_count; i++) {
502 if (command->capabilityData->data.handles.handle[i] > EK_CERT_RANGE) {
503 command->cert_count = i;
504 }
505 }
506
507 if (command->cert_count == 0) {
508 /* No certificates were found the cert range. */
509 Esys_Free(command->capabilityData);
510 command->capabilityData = NULL;
511 context->state = PROVISION_CHECK_FOR_VENDOR_CERT;
512 return TSS2_FAPI_RC_TRY_AGAIN;
513 }
514 fallthrough;
515
516 statecase(context->state, PROVISION_GET_CERT_NV);
517
518 /* Detemine the NV index of the certifcate from the read capability data. */
519 command->cert_nv_idx
520 = command->capabilityData->data.handles.handle[command->cert_count-1];
521
522 if ((command->cert_nv_idx % 2) || /**< Certificates will be stored at even address */
523 command->cert_nv_idx == 0x01c00004 || /**< RSA template */
524 command->cert_nv_idx == 0x01c0000c) { /**< ECC template */
525 if (command->cert_count > 1) {
526 command->cert_count -= 1;
527 /* Check next certificate */
528 context->state = PROVISION_GET_CERT_NV;
529 return TSS2_FAPI_RC_TRY_AGAIN;
530 } else {
531 /* All certificates have been read, the EK can be written. */
532 context->state = PROVISION_EK_WRITE_PREPARE;
533 return TSS2_FAPI_RC_TRY_AGAIN;
534 }
535 }
536 ifapi_init_hierarchy_object(&nvCmd->auth_object, TPM2_RH_OWNER);
537
538 /* Create esys object for the NV object of the certificate. */
539 r = Esys_TR_FromTPMPublic_Async(context->esys, command->cert_nv_idx,
540 ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE);
541 goto_if_error_reset_state(r, "Esys_TR_FromTPMPublic_Async", error_cleanup);
542
543 context->state = PROVISION_GET_CERT_NV_FINISH;
544 fallthrough;
545
546 statecase(context->state, PROVISION_GET_CERT_NV_FINISH);
547 r = Esys_TR_FromTPMPublic_Finish(context->esys,
548 &command->esys_nv_cert_handle);
549 return_try_again(r);
550 goto_if_error_reset_state(r, "TR_FromTPMPublic_Finish", error_cleanup);
551
552 /* Read public to get size of certificate */
553 r = Esys_NV_ReadPublic_Async(context->esys, command->esys_nv_cert_handle,
554 ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE);
555 goto_if_error_reset_state(r, "Esys_NV_ReadPublic_Async", error_cleanup);
556
557 context->state = PROVISION_GET_CERT_READ_PUBLIC;
558 fallthrough;
559
560 statecase(context->state, PROVISION_GET_CERT_READ_PUBLIC);
561 r = Esys_NV_ReadPublic_Finish(context->esys, &nvPublic, NULL);
562 return_try_again(r);
563
564 goto_if_error(r, "Error: nv read public", error_cleanup);
565
566 /* TPMA_NV_NO_DA is set for NV certificate */
567 nvCmd->nv_object.misc.nv.public.nvPublic.attributes = TPMA_NV_NO_DA;
568
569 /* Prepare context for nv read */
570 nvCmd->data_idx = 0;
571 nvCmd->auth_index = ESYS_TR_RH_OWNER;
572 nvCmd->numBytes = nvPublic->nvPublic.dataSize;
573 nvCmd->esys_handle = command->esys_nv_cert_handle;
574 nvCmd->offset = 0;
575 command->pem_cert = NULL;
576 context->session1 = ESYS_TR_PASSWORD;
577 context->session2 = ESYS_TR_NONE;
578 nvCmd->nv_read_state = NV_READ_INIT;
579 memset(&nvCmd->nv_object, 0, sizeof(IFAPI_OBJECT));
580 SAFE_FREE(nvPublic);
581
582 context->state = PROVISION_READ_CERT;
583 fallthrough;
584
585 statecase(context->state, PROVISION_READ_CERT);
586 TPM2B_PUBLIC public_key;
587 char * root_ca_file;
588
589 /* The NV object of the certificate will be read asynchronous. */
590 r = ifapi_nv_read(context, &certData, &certSize);
591 return_try_again(r);
592 goto_if_error_reset_state(r, " FAPI NV_Read", error_cleanup);
593
594 /* For storage in key store the certificate will be converted to PEM. */
595 r = ifapi_cert_to_pem(certData, certSize, &command->pem_cert,
596 &command->cert_key_type, &public_key);
597 SAFE_FREE(certData);
598 goto_if_error(r, "Convert certificate to pem.", error_cleanup);
599
600 /* Check whether the EKs public key corresponds to the certificate. */
601 if (ifapi_cmp_public_key(&pkeyObject->misc.key.public, &public_key)) {
602 context->state = PROVISION_PREPARE_READ_ROOT_CERT;
603 return TSS2_FAPI_RC_TRY_AGAIN;
604 } else {
605 /* Certificate not appropriate for current EK key type */
606 command->cert_count -= 1;
607 SAFE_FREE(command->pem_cert);
608 if (command->cert_count > 0) {
609 /* Check next certificate */
610 context->state = PROVISION_GET_CERT_NV;
611 return TSS2_FAPI_RC_TRY_AGAIN;
612 }
613 }
614
615 goto_error(r, TSS2_FAPI_RC_NO_CERT, "No EK certificate found.",
616 error_cleanup);
617
618 statecase(context->state, PROVISION_PREPARE_READ_ROOT_CERT);
619 /* Prepare reading of root certificate. */
620 root_ca_file = getenv("FAPI_TEST_ROOT_CERT");
621 if (!root_ca_file) {
622 context->state = PROVISION_EK_CHECK_CERT;
623 return TSS2_FAPI_RC_TRY_AGAIN;
624 }
625 r = ifapi_io_read_async(&context->io, root_ca_file);
626 return_try_again(r);
627 goto_if_error2(r, "Reading certificate %s", error_cleanup, root_ca_file);
628
629 fallthrough;
630
631 statecase(context->state, PROVISION_READ_ROOT_CERT);
632 r = ifapi_io_read_finish(&context->io, (uint8_t **) &command->root_crt, NULL);
633 return_try_again(r);
634 goto_if_error(r, "Reading root certificate failed", error_cleanup);
635
636 fallthrough;
637
638 statecase(context->state, PROVISION_EK_CHECK_CERT);
639 /* The EK certificate will be verified against the FAPI list of root certificates. */
640 r = ifapi_verify_ek_cert(command->root_crt, command->intermed_crt, command->pem_cert);
641 SAFE_FREE(command->root_crt);
642 SAFE_FREE(command->intermed_crt);
643 goto_if_error2(r, "Verify EK certificate", error_cleanup);
644
645 fallthrough;
646
647 statecase(context->state, PROVISION_EK_WRITE_PREPARE);
648 pkeyObject->objectType = IFAPI_KEY_OBJ;
649 pkeyObject->system = command->public_templ.system;
650 strdup_check(pkeyObject->misc.key.certificate, command->pem_cert, r, error_cleanup);
651 SAFE_FREE(command->pem_cert);
652
653 /* Perform esys serialization if necessary */
654 r = ifapi_esys_serialize_object(context->esys,
655 pkeyObject);
656 goto_if_error(r, "Prepare serialization", error_cleanup);
657
658 /* Start writing the EK to the key store */
659 r = ifapi_keystore_store_async(&context->keystore, &context->io, "HE/EK",
660 pkeyObject);
661 goto_if_error_reset_state(r, "Could not open: %sh", error_cleanup, "HE/EK");
662
663 fallthrough;
664
665 statecase(context->state, PROVISION_EK_WRITE);
666 /* Finish writing the EK to the key store */
667 r = ifapi_keystore_store_finish(&context->keystore, &context->io);
668 return_try_again(r);
669 goto_if_error_reset_state(r, "write_finish failed", error_cleanup);
670
671 /* Clean objects used for EK computation */
672 ifapi_cleanup_ifapi_object(pkeyObject);
673 memset(&command->public_templ, 0, sizeof(IFAPI_KEY_TEMPLATE));
674 SAFE_FREE(hierarchy->misc.hierarchy.description);
675
676 /*
677 * Adaption of the lockout hierarchy to the passed parameters
678 * and the current profile.
679 */
680 ifapi_init_hierarchy_object(hierarchy, ESYS_TR_RH_LOCKOUT);
681 strdup_check(hierarchy->misc.hierarchy.description, "Lockout Hierarchy",
682 r, error_cleanup);
683
684 if (!command->authValueLockout ||
685 strcmp(command->authValueLockout, "") == 0) {
686 context->state = PROVISION_LOCKOUT_CHANGE_POLICY;
687 /* Auth value of lockout hierarchy will not be changed. */
688 return TSS2_FAPI_RC_TRY_AGAIN;
689 }
690
691 if (strlen(command->authValueLockout) > sizeof(TPMU_HA)) {
692 goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
693 "Password too long.", error_cleanup);
694 }
695 /* Copy auth value into context. */
696 memcpy(&command->hierarchy_auth.buffer[0],
697 command->authValueLockout, strlen(command->authValueLockout));
698 command->hierarchy_auth.size = strlen(command->authValueLockout);
699 context->state = PROVISION_CHANGE_LOCKOUT_AUTH;
700 return TSS2_FAPI_RC_TRY_AGAIN;
701
702 statecase(context->state, PROVISION_WAIT_FOR_SRK_PERSISTENT);
703 r = Esys_EvictControl_Finish(context->esys, &pkeyObject->handle);
704 return_try_again(r);
705 goto_if_error(r, "Evict control failed", error_cleanup);
706
707 /* The SRK was made persistent and can be written to key store. */
708 context->state = PROVISION_SRK_WRITE_PREPARE;
709 return TSS2_FAPI_RC_TRY_AGAIN;
710
711 statecase(context->state, PROVISION_WAIT_FOR_EK_PERSISTENT);
712 r = Esys_EvictControl_Finish(context->esys, &pkeyObject->handle);
713 return_try_again(r);
714 goto_if_error(r, "Evict control failed", error_cleanup);
715
716 context->state = PROVISION_INIT_GET_CAP2;
717 return TSS2_FAPI_RC_TRY_AGAIN;
718
719 statecase(context->state, PROVISION_CHANGE_LOCKOUT_AUTH);
720
721 /* If a lockout auth value is provided by profile, the auth value
722 if the hierarchy will be changed asynchronous. */
723 r = ifapi_change_auth_hierarchy(context, ESYS_TR_RH_LOCKOUT,
724 &command->hierarchy, &command->hierarchy_auth);
725 return_try_again(r);
726 goto_if_error(r, "Change auth hierarchy.", error_cleanup);
727
728 context->state = PROVISION_LOCKOUT_CHANGE_POLICY;
729 fallthrough;
730
731 statecase(context->state, PROVISION_LOCKOUT_CHANGE_POLICY);
732 /* If a lockout policy is provided by profile, the policy will be
733 assigned to lockout hierarchy asynchronous. */
734 r = ifapi_change_policy_hierarchy(context, ESYS_TR_RH_LOCKOUT,
735 hierarchy, defaultProfile->lockout_policy);
736 return_try_again(r);
737 goto_if_error(r, "Change policy LOCKOUT", error_cleanup);
738
739 /* Start writing the lockout hierarchy object to the key store */
740 r = ifapi_keystore_store_async(&context->keystore, &context->io, "/LOCKOUT",
741 &command->hierarchy);
742 goto_if_error_reset_state(r, "Could not open: %sh",
743 error_cleanup, "/LOCKOUT");
744
745 context->state = PROVISION_WRITE_LOCKOUT;
746 fallthrough;
747
748 statecase(context->state, PROVISION_WRITE_LOCKOUT);
749 /* Finish writing the lockout hierarchy to the key store */
750 r = ifapi_keystore_store_finish(&context->keystore, &context->io);
751 return_try_again(r);
752 goto_if_error_reset_state(r, "write_finish failed", error_cleanup);
753
754 SAFE_FREE(hierarchy->misc.hierarchy.description);
755
756 /*
757 * Adaption of the Endorsement hierarchy to the passed parameters
758 * and the current profile.
759 */
760 ifapi_init_hierarchy_object(hierarchy, ESYS_TR_RH_ENDORSEMENT);
761 strdup_check(hierarchy->misc.hierarchy.description,
762 "Endorsement Hierarchy", r, error_cleanup);
763
764 context->state = PROVISION_CHANGE_EH_CHECK;
765 fallthrough;
766
767 statecase(context->state, PROVISION_CHANGE_EH_CHECK);
768 if (command->authValueEh) {
769 context->state = PROVISION_CHANGE_EH_AUTH;
770 /* Save auth value of endorsement hierarchy in context. */
771 memcpy(&command->hierarchy_auth.buffer[0], command->authValueEh,
772 strlen(command->authValueEh));
773 command->hierarchy_auth.size = strlen(command->authValueEh);
774 } else {
775 /* Auth value of lockout hierarchy will not be changed. */
776 context->state = PROVISION_EH_CHANGE_POLICY;
777 return TSS2_FAPI_RC_TRY_AGAIN;
778 }
779 context->state = PROVISION_CHANGE_EH_AUTH;
780 fallthrough;
781
782 statecase(context->state, PROVISION_CHANGE_EH_AUTH);
783 /* If an endorsement hierarchy auth value is provided by profile,
784 the auth value will be changed asynchronous. */
785 r = ifapi_change_auth_hierarchy(context, ESYS_TR_RH_ENDORSEMENT,
786 &command->hierarchy, &command->hierarchy_auth);
787 return_try_again(r);
788 goto_if_error(r, "Change auth hierarchy.", error_cleanup);
789
790 context->state = PROVISION_EH_CHANGE_POLICY;
791 fallthrough;
792
793 statecase(context->state, PROVISION_EH_CHANGE_POLICY);
794 /* If an endorsement hierarchy policy is provided by profile,
795 the policy will be assigned asynchronous. */
796 r = ifapi_change_policy_hierarchy(context, ESYS_TR_RH_ENDORSEMENT,
797 hierarchy, defaultProfile->eh_policy);
798 return_try_again(r);
799 goto_if_error(r, "Change policy EH", error_cleanup);
800
801 /* Start writing the endorsement hierarchy object to the key store */
802 r = ifapi_keystore_store_async(&context->keystore, &context->io, "/HE",
803 &command->hierarchy);
804 goto_if_error_reset_state(r, "Could not open: %sh", error_cleanup, "/HE");
805
806 context->state = PROVISION_WRITE_EH;
807 fallthrough;
808
809 statecase(context->state, PROVISION_WRITE_EH);
810 /* Finish writing the endorsement hierarchy to the key store */
811 r = ifapi_keystore_store_finish(&context->keystore, &context->io);
812 return_try_again(r);
813 return_if_error_reset_state(r, "write_finish failed");
814
815 SAFE_FREE(hierarchy->misc.hierarchy.description);
816
817 /*
818 * Adaption of the owner hierarchy to the passed parameters
819 * and the current profile.
820 */
821 ifapi_init_hierarchy_object(hierarchy, ESYS_TR_RH_OWNER);
822 strdup_check(hierarchy->misc.hierarchy.description,
823 "Owner Hierarchy", r, error_cleanup);
824
825 context->state = PROVISION_CHANGE_SH_CHECK;
826 fallthrough;
827
828 statecase(context->state, PROVISION_CHANGE_SH_CHECK);
829 if (command->authValueSh) {
830 context->state = PROVISION_CHANGE_SH_AUTH;
831 /* Save auth value of owner hierarchy in context. */
832 memcpy(&command->hierarchy_auth.buffer[0], command->authValueSh,
833 strlen(command->authValueSh));
834 command->hierarchy_auth.size = strlen(command->authValueSh);
835 context->state = PROVISION_CHANGE_SH_AUTH;
836 } else {
837 /* Auth value of owner hierarchy will not be changed. */
838 context->state = PROVISION_SH_CHANGE_POLICY;
839 return TSS2_FAPI_RC_TRY_AGAIN;
840 }
841 context->state = PROVISION_CHANGE_SH_AUTH;
842 fallthrough;
843
844 statecase(context->state, PROVISION_CHANGE_SH_AUTH);
845 /* If an owner hierarchy auth value is provided by profile,
846 the auth value will be changed asynchronous. */
847 r = ifapi_change_auth_hierarchy(context, ESYS_TR_RH_OWNER,
848 &command->hierarchy, &command->hierarchy_auth);
849 return_try_again(r);
850 goto_if_error(r, "Change auth hierarchy.", error_cleanup);
851
852 context->state = PROVISION_SH_CHANGE_POLICY;
853 fallthrough;
854
855 statecase(context->state, PROVISION_SH_CHANGE_POLICY);
856 /* If an owner hierarchy policy is provided by profile,
857 the policy will be assigned asynchronous. */
858 r = ifapi_change_policy_hierarchy(context, ESYS_TR_RH_OWNER,
859 hierarchy, defaultProfile->sh_policy);
860 return_try_again(r);
861 goto_if_error(r, "Change policy SH", error_cleanup);
862
863 /* Start writing the owner hierarchy object to the key store */
864 r = ifapi_keystore_store_async(&context->keystore, &context->io, "/HS",
865 &command->hierarchy);
866 goto_if_error_reset_state(r, "Could not open: %sh", error_cleanup, "/HS");
867 context->state = PROVISION_WRITE_SH;
868 fallthrough;
869
870 statecase(context->state, PROVISION_WRITE_SH);
871 /* The onwer hierarchy object will be written to key store. */
872 r = ifapi_keystore_store_finish(&context->keystore, &context->io);
873 return_try_again(r);
874 goto_if_error_reset_state(r, "write_finish failed", error_cleanup);
875 fallthrough;
876
877 statecase(context->state, PROVISION_FINISHED);
878 if (!context->srk_persistent && context->srk_handle != ESYS_TR_NONE) {
879 /* Prepare the flushing of a non persistent SRK. */
880 r = Esys_FlushContext_Async(context->esys, context->srk_handle);
881 goto_if_error(r, "Flush SRK", error_cleanup);
882 }
883 fallthrough;
884
885 /* Flush the SRK if not persistent */
886 statecase(context->state, PROVISION_FLUSH_SRK);
887 if (!context->srk_persistent && context->srk_handle != ESYS_TR_NONE) {
888 r = Esys_FlushContext_Finish(context->esys);
889 try_again_or_error_goto(r, "Flush SRK", error_cleanup);
890
891 context->srk_handle = ESYS_TR_NONE;
892
893 }
894 if (!context->ek_persistent && context->ek_handle != ESYS_TR_NONE) {
895 /* Prepare the flushing of a non persistent EK. */
896 r = Esys_FlushContext_Async(context->esys, context->ek_handle);
897 goto_if_error(r, "Flush EK", error_cleanup);
898 }
899 fallthrough;
900
901 /* Flush the EK if not persistent */
902 statecase(context->state, PROVISION_FLUSH_EK);
903 if (!context->ek_persistent && context->ek_handle != ESYS_TR_NONE) {
904 r = Esys_FlushContext_Finish(context->esys);
905 try_again_or_error_goto(r, "Flush EK", error_cleanup);
906
907 context->ek_handle = ESYS_TR_NONE;
908 }
909
910 context->state = _FAPI_STATE_INIT;
911 break;
912
913 /*
914 * The vendor ID stored in the TPM has to be read to check whether
915 * a special certificate handling is needed.
916 */
917 statecase(context->state, PROVISION_CHECK_FOR_VENDOR_CERT);
918 /* Prepare reading the vendor ID */
919 r = Esys_GetCapability_Async(context->esys,
920 ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
921 TPM2_CAP_TPM_PROPERTIES, TPM2_PT_MANUFACTURER, 1);
922 goto_if_error(r, "Esys_GetCapability_Async", error_cleanup);
923
924 fallthrough;
925
926 statecase(context->state, PROVISION_GET_VENDOR);
927 /* Get the vendor ID asynchronous. */
928 r = Esys_GetCapability_Finish(context->esys, &moreData, capabilityData);
929 return_try_again(r);
930 goto_if_error_reset_state(r, "GetCapablity_Finish", error_cleanup);
931
932 if ((*capabilityData)->data.tpmProperties.tpmProperty[0].value == VENDOR_INTC) {
933 /* Get INTEL certificate for EK public hash via web */
934 uint8_t *cert_buffer = NULL;
935 size_t cert_size;
936 TPM2B_PUBLIC public;
937 r = ifapi_get_intl_ek_certificate(context, &pkey->public, &cert_buffer,
938 &cert_size);
939 goto_if_error_reset_state(r, "Get certificates", error_cleanup);
940
941 r = ifapi_cert_to_pem(cert_buffer, cert_size, &command->pem_cert,
942 NULL, &public);
943 SAFE_FREE(cert_buffer);
944 goto_if_error_reset_state(r, "Convert certificate buffer to PEM.",
945 error_cleanup);
946 }
947 SAFE_FREE(*capabilityData);
948 context->state = PROVISION_EK_WRITE_PREPARE;
949 return TSS2_FAPI_RC_TRY_AGAIN;
950
951 statecasedefault(context->state);
952 }
953
954 error_cleanup:
955 /* Primaries might not have been flushed in error cases */
956 ifapi_primary_clean(context);
957 SAFE_FREE(command->root_crt);
958 SAFE_FREE(*capabilityData);
959 SAFE_FREE(hierarchy->misc.hierarchy.description);
960 SAFE_FREE(command->authValueLockout);
961 SAFE_FREE(command->authValueEh);
962 SAFE_FREE(command->authValueSh);
963 SAFE_FREE(command->pem_cert);
964 SAFE_FREE(certData);
965 SAFE_FREE(nvPublic);
966 LOG_TRACE("finished");
967 return r;
968 }
969