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 <string.h>
12 #include <stdlib.h>
13
14 #include "tss2_mu.h"
15 #include "fapi_util.h"
16 #include "fapi_crypto.h"
17 #include "fapi_policy.h"
18 #include "ifapi_helpers.h"
19 #include "ifapi_json_deserialize.h"
20 #include "tpm_json_deserialize.h"
21 #define LOGMODULE fapi
22 #include "util/log.h"
23 #include "util/aux_util.h"
24
25 /** Copy policy digest.
26 *
27 * One digest is copied from certain position in a policy list to the
28 * same position in a second list.
29 *
30 * @param[out] dest The digest list to which the new value is added.
31 * @param[in] src The digest list with the value to be copied.
32 * @param[in] digest_idx The index of the digest to be copied.
33 * @param[in] hash_size The number of bytes to be copied.
34 * @param[in] txt Text which will be used for additional logging information..
35 * @retval TSS2_RC_SUCCESS on success.
36 */
37 static void
copy_policy_digest(TPML_DIGEST_VALUES * dest,TPML_DIGEST_VALUES * src,size_t digest_idx,size_t hash_size,char * txt)38 copy_policy_digest(TPML_DIGEST_VALUES *dest, TPML_DIGEST_VALUES *src,
39 size_t digest_idx, size_t hash_size, char *txt)
40 {
41 memcpy(&dest->digests[digest_idx].digest, &src->digests[digest_idx].digest,
42 hash_size);
43 dest->digests[digest_idx].hashAlg = src->digests[digest_idx].hashAlg;
44 LOGBLOB_DEBUG((uint8_t *)&dest->digests[digest_idx].digest, hash_size,
45 "%s : Copy digest size: %zu", txt, hash_size);
46 dest->count = src->count;
47 }
48
49 /** Logdefault policy digest.
50 *
51 * @param[in] dest The digest to be logged.
52 * @param[in] digest_idx The index of the digest to be logged
53 * @param[in] hash_size The number of bytes to be logged
54 * @param[in] txt Text which will be used for additional logging information.
55 */
56 static void
log_policy_digest(TPML_DIGEST_VALUES * dest,size_t digest_idx,size_t hash_size,char * txt)57 log_policy_digest(TPML_DIGEST_VALUES *dest, size_t digest_idx, size_t hash_size,
58 char *txt)
59 {
60 LOGBLOB_DEBUG((uint8_t *)&dest->digests[digest_idx].digest, hash_size,
61 "Digest %s", txt);
62 }
63
64 /** Calculate a policy digest for a certain PCR selection.
65 *
66 * From a PCR list the list of PCR values and the corresponding PCR digest
67 * is computed. The passed policy digest will be extended with this data
68 * and also with the policy command code.
69 *
70 * @param[in] policy The policy with the list of selected PCRs.
71 * @param[in,out] current_digest The digest list which has to be updated.
72 * @param[in] current_hash_alg The hash algorithm used for the policy computation.
73 *
74 * @retval TSS2_RC_SUCCESS on success.
75 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
76 * the function.
77 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
78 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
79 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
80 */
81 TSS2_RC
ifapi_compute_policy_pcr(TPMS_POLICYPCR * policy,TPML_DIGEST_VALUES * current_digest,TPMI_ALG_HASH current_hash_alg)82 ifapi_compute_policy_pcr(
83 TPMS_POLICYPCR *policy,
84 TPML_DIGEST_VALUES *current_digest,
85 TPMI_ALG_HASH current_hash_alg)
86 {
87 TSS2_RC r = TSS2_RC_SUCCESS;
88 IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext = NULL;
89 TPML_PCR_SELECTION pcr_selection;
90 size_t digest_idx;
91 TPM2B_DIGEST pcr_digest;
92 size_t hash_size;
93
94 LOG_TRACE("call");
95
96 if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
97 goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
98 "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
99 current_hash_alg);
100 }
101
102 /* Compute of the index of the current policy in the passed digest list */
103 r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
104 return_if_error(r, "Get hash alg for digest.");
105
106 /* Compute PCR selection and pcr digest */
107 r = ifapi_compute_policy_digest(policy->pcrs, &pcr_selection,
108 current_hash_alg, &pcr_digest);
109 return_if_error(r, "Compute policy digest and selection.");
110
111 LOG_TRACE("Compute policy pcr");
112 r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
113 return_if_error(r, "crypto hash start");
114
115 /* Update the passed policy. */
116 HASH_UPDATE_BUFFER(cryptoContext,
117 ¤t_digest->digests[digest_idx].digest, hash_size,
118 r, cleanup);
119 HASH_UPDATE(cryptoContext, TPM2_CC, TPM2_CC_PolicyPCR, r, cleanup);
120 /* The marshaled version of the digest list will be added. */
121 HASH_UPDATE(cryptoContext, TPML_PCR_SELECTION, &pcr_selection, r, cleanup);
122 HASH_UPDATE_BUFFER(cryptoContext, &pcr_digest.buffer[0], hash_size, r,
123 cleanup);
124
125 r = ifapi_crypto_hash_finish(&cryptoContext,
126 (uint8_t *) & current_digest->
127 digests[digest_idx].digest, &hash_size);
128 return_if_error(r, "crypto hash finish");
129
130 cleanup:
131 if (cryptoContext)
132 ifapi_crypto_hash_abort(&cryptoContext);
133 return r;
134 }
135
136 /** Calculate a policy digest for a TPM2B object name, and a policy reference.
137 *
138 * A policy hash based on a passed policy digest, the policy command code,
139 * optionally the name, and the policy reference will be computed.
140 * The calculation is carried out in two steps. First a hash with the
141 * command code and the passed digest, and optionaly the name is computed.
142 * This digest, together with the other parameters is used to compute
143 * the final policy digest.
144 *
145 * @param[in] command_code The TPM command code of the policy command.
146 * @param[in] name The name of a key or a NV object.
147 * @param[in] policyRef The policy reference value.
148 * @param[in] hash_size The digest size of the used hash algorithm.
149 * @param[in] current_hash_alg The used has algorithm.
150 * @param[in,out] digest The policy digest which will be extended.
151 *
152 * @retval TSS2_RC_SUCCESS on success.
153 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
154 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
155 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
156 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
157 * the function.
158 */
159 static TSS2_RC
calculate_policy_key_param(TPM2_CC command_code,TPM2B_NAME * name,TPM2B_NONCE * policyRef,size_t hash_size,TPMI_ALG_HASH current_hash_alg,TPMU_HA * digest)160 calculate_policy_key_param(
161 TPM2_CC command_code,
162 TPM2B_NAME *name,
163 TPM2B_NONCE *policyRef,
164 size_t hash_size,
165 TPMI_ALG_HASH current_hash_alg,
166 TPMU_HA *digest)
167 {
168 TSS2_RC r = TSS2_RC_SUCCESS;
169 IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext = NULL;
170
171 r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
172 return_if_error(r, "crypto hash start");
173
174 LOGBLOB_DEBUG((uint8_t *) digest, hash_size, "Digest Start");
175
176 /* First compute hash from passed policy digest and command code
177 and optionally the object name */
178 HASH_UPDATE_BUFFER(cryptoContext, digest, hash_size, r, cleanup);
179 HASH_UPDATE(cryptoContext, TPM2_CC, command_code, r, cleanup);
180 if (name && name->size > 0) {
181 LOGBLOB_DEBUG(&name->name[0], name->size, "Key name");
182 HASH_UPDATE_BUFFER(cryptoContext, &name->name[0],
183 name->size, r, cleanup);
184 }
185 r = ifapi_crypto_hash_finish(&cryptoContext,
186 (uint8_t *) digest, &hash_size);
187 LOGBLOB_DEBUG((uint8_t *) digest, hash_size, "Digest Finish");
188 return_if_error(r, "crypto hash finish");
189
190 /* Use policyRef for second hash computation */
191 if (policyRef) {
192 r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
193 return_if_error(r, "crypto hash start");
194
195 HASH_UPDATE_BUFFER(cryptoContext, digest, hash_size, r, cleanup);
196 HASH_UPDATE_BUFFER(cryptoContext, &policyRef->buffer[0],
197 policyRef->size, r, cleanup);
198 r = ifapi_crypto_hash_finish(&cryptoContext,
199 (uint8_t *) digest, &hash_size);
200 return_if_error(r, "crypto hash finish");
201 }
202
203 cleanup:
204 if (cryptoContext)
205 ifapi_crypto_hash_abort(&cryptoContext);
206 return r;
207 }
208
209 /** Calculate a policy digest for a signed policy.
210 *
211 * Based on the command code, the public key, and the policy reference
212 * stored in the policy the new policy digest is computed by the function
213 * calculate_policy_key_param().
214 *
215 * @param[in] policy The policy with the public key and the policy reference.
216 * @param[in,out] current_digest The digest list which has to be updated.
217 * @param[in] current_hash_alg The hash algorithm used for the policy computation.
218 *
219 * @retval TSS2_RC_SUCCESS on success.
220 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
221 * the function.
222 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
223 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
224 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
225 */
226 TSS2_RC
ifapi_calculate_policy_signed(TPMS_POLICYSIGNED * policy,TPML_DIGEST_VALUES * current_digest,TPMI_ALG_HASH current_hash_alg)227 ifapi_calculate_policy_signed(
228 TPMS_POLICYSIGNED *policy,
229 TPML_DIGEST_VALUES *current_digest,
230 TPMI_ALG_HASH current_hash_alg)
231 {
232 TSS2_RC r = TSS2_RC_SUCCESS;
233 size_t digest_idx;
234 size_t hash_size;
235
236 LOG_DEBUG("call");
237
238 if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
239 goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
240 "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
241 current_hash_alg);
242 }
243
244 /* Compute of the index of the current policy in the passed digest list */
245 r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
246 return_if_error(r, "Get hash alg for digest.");
247
248 r = calculate_policy_key_param(TPM2_CC_PolicySigned,
249 &policy->publicKey,
250 &policy->policyRef, hash_size,
251 current_hash_alg,
252 ¤t_digest->digests[digest_idx].digest);
253 goto_if_error(r, "crypto hash start", cleanup);
254
255 cleanup:
256 return r;
257 }
258
259 /** Calculate a policy digest for a policy stored in an approved NV index.
260 *
261 * Based on the command code, and the computed NV name the new policy digest
262 * is computed by the function calculate_policy_key_param().
263 *
264 * @param[in] policy The policy with the public information of the NV index.
265 * @param[in,out] current_digest The digest list which has to be updated.
266 * @param[in] current_hash_alg The hash algorithm used for the policy computation.
267 *
268 * @retval TSS2_RC_SUCCESS on success.
269 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
270 * the function.
271 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
272 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
273 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
274 */
275 TSS2_RC
ifapi_calculate_policy_authorize_nv(TPMS_POLICYAUTHORIZENV * policy,TPML_DIGEST_VALUES * current_digest,TPMI_ALG_HASH current_hash_alg)276 ifapi_calculate_policy_authorize_nv(
277 TPMS_POLICYAUTHORIZENV *policy,
278 TPML_DIGEST_VALUES *current_digest,
279 TPMI_ALG_HASH current_hash_alg)
280 {
281 TSS2_RC r = TSS2_RC_SUCCESS;
282 size_t digest_idx;
283 size_t hash_size;
284 TPM2B_NAME nv_name;
285
286 LOG_DEBUG("call");
287
288 /* Written flag has to be set for policy calculation, because during
289 policy execution it will be set. */
290 policy->nvPublic.nvPublic.attributes |= TPMA_NV_WRITTEN;
291
292 r = ifapi_nv_get_name(&policy->nvPublic, &nv_name);
293 return_if_error(r, "Compute NV name");
294
295 if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
296 goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
297 "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
298 current_hash_alg);
299 }
300
301 /* Compute of the index of the current policy in the passed digest list */
302 r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
303 return_if_error(r, "Get hash alg for digest.");
304
305 r = calculate_policy_key_param(TPM2_CC_PolicyAuthorizeNV,
306 &nv_name,
307 NULL, hash_size, current_hash_alg,
308 ¤t_digest->digests[digest_idx].digest);
309 goto_if_error(r, "crypto hash start", cleanup);
310
311 cleanup:
312 return r;
313 }
314
315 /** Calculate a policy digest to allow duplication force a selected new parent.
316 *
317 * Based on the command code, the name of the new parent, and the include object
318 * switch the new policy digest is computed.
319 *
320 * @param[in] policy The policy with the new parent information.
321 * @param[in,out] current_digest The digest list which has to be updated.
322 * @param[in] current_hash_alg The hash algorithm used for the policy computation.
323 *
324 * @retval TSS2_RC_SUCCESS on success.
325 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
326 * the function.
327 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
328 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
329 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
330 */
331 TSS2_RC
ifapi_calculate_policy_duplicate(TPMS_POLICYDUPLICATIONSELECT * policy,TPML_DIGEST_VALUES * current_digest,TPMI_ALG_HASH current_hash_alg)332 ifapi_calculate_policy_duplicate(
333 TPMS_POLICYDUPLICATIONSELECT *policy,
334 TPML_DIGEST_VALUES *current_digest,
335 TPMI_ALG_HASH current_hash_alg)
336 {
337 TSS2_RC r = TSS2_RC_SUCCESS;
338 IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext = NULL;
339 size_t digest_idx;
340 size_t hash_size;
341
342 LOG_DEBUG("call");
343
344 if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
345 goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
346 "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
347 current_hash_alg);
348 }
349
350 /* Compute of the index of the current policy in the passed digest list */
351 r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
352 return_if_error(r, "Get hash alg for digest.");
353
354 LOG_TRACE("Compute policy");
355 r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
356 return_if_error(r, "crypto hash start");
357
358 /* Update the policy digest */
359 HASH_UPDATE_BUFFER(cryptoContext,
360 ¤t_digest->digests[digest_idx].digest, hash_size,
361 r, cleanup);
362 HASH_UPDATE(cryptoContext, TPM2_CC, TPM2_CC_PolicyDuplicationSelect, r,
363 cleanup);
364 LOGBLOB_DEBUG(&policy->newParentName.name[0], policy->newParentName.size,
365 "Policy Duplicate Parent Name");
366 HASH_UPDATE_BUFFER(cryptoContext, &policy->newParentName.name[0],
367 policy->newParentName.size, r, cleanup);
368 HASH_UPDATE(cryptoContext, BYTE, policy->includeObject, r, cleanup);
369
370 r = ifapi_crypto_hash_finish(&cryptoContext,
371 (uint8_t *) & current_digest->
372 digests[digest_idx].digest, &hash_size);
373 return_if_error(r, "crypto hash finish");
374
375 LOGBLOB_DEBUG((uint8_t *) & current_digest->digests[digest_idx].digest,
376 hash_size, "Policy Duplicate digest");
377
378 cleanup:
379 if (cryptoContext)
380 ifapi_crypto_hash_abort(&cryptoContext);
381 return r;
382 }
383
384 /** Calculate a policy digest for a placeholder policy.
385 *
386 * The placeholder policy can be extended during execution by a
387 * signed policy, which can be verified by using the parameters of
388 * this placeholder policy.
389 * Based on the command code, the key name of the signing key and
390 * a policy reference the new policy digest is computed by the
391 * function calculate_policy_key_param().
392 *
393 * @param[in] policy The policy with the name of the public key and the
394 * policy reference.
395 * @param[in,out] current_digest The digest list which has to be updated.
396 * @param[in] current_hash_alg The hash algorithm used for the policy computation.
397 *
398 * @retval TSS2_RC_SUCCESS on success.
399 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
400 * the function.
401 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
402 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
403 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
404 */
405 TSS2_RC
ifapi_calculate_policy_authorize(TPMS_POLICYAUTHORIZE * policy,TPML_DIGEST_VALUES * current_digest,TPMI_ALG_HASH current_hash_alg)406 ifapi_calculate_policy_authorize(
407 TPMS_POLICYAUTHORIZE *policy,
408 TPML_DIGEST_VALUES *current_digest,
409 TPMI_ALG_HASH current_hash_alg)
410 {
411 TSS2_RC r = TSS2_RC_SUCCESS;
412 size_t digest_idx;
413 size_t hash_size;
414
415 LOG_DEBUG("call");
416
417 if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
418 goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
419 "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
420 current_hash_alg);
421 }
422
423 /* Compute of the index of the current policy in the passed digest list */
424 r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
425 return_if_error(r, "Get hash alg for digest.");
426
427 r = calculate_policy_key_param(TPM2_CC_PolicyAuthorize,
428 &policy->keyName,
429 &policy->policyRef, hash_size,
430 current_hash_alg,
431 ¤t_digest->digests[digest_idx].digest);
432 goto_if_error(r, "crypto hash start", cleanup);
433
434 cleanup:
435 return r;
436 }
437
438 /** Calculate a policy for adding secret-based authorization.
439 *
440 * During execution proving the knowledge of the secrect auth value of a certain
441 * object is required. The name of this object and a policy reference is used
442 * for policy calculation.
443 * Based on the command code, the object name and a policy reference the new
444 * policy digest is computed by the function calculate_policy_key_param().
445 *
446 * @param[in] policy The policy with the object name of the object to be
447 * authorized and the policy reference.
448 * @param[in,out] current_digest The digest list which has to be updated.
449 * @param[in] current_hash_alg The hash algorithm used for the policy computation.
450 *
451 * @retval TSS2_RC_SUCCESS on success.
452 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
453 * the function.
454 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
455 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
456 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
457 */
458 TSS2_RC
ifapi_calculate_policy_secret(TPMS_POLICYSECRET * policy,TPML_DIGEST_VALUES * current_digest,TPMI_ALG_HASH current_hash_alg)459 ifapi_calculate_policy_secret(
460 TPMS_POLICYSECRET *policy,
461 TPML_DIGEST_VALUES *current_digest,
462 TPMI_ALG_HASH current_hash_alg)
463 {
464 TSS2_RC r = TSS2_RC_SUCCESS;
465 size_t digest_idx;
466 size_t hash_size;
467
468 LOG_DEBUG("call");
469
470 if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
471 goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
472 "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
473 current_hash_alg);
474 }
475
476 /* Compute of the index of the current policy in the passed digest list */
477 r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
478 return_if_error(r, "Get hash alg for digest.");
479
480 /* Update the policy */
481 r = calculate_policy_key_param(TPM2_CC_PolicySecret,
482 (TPM2B_NAME *)&policy->objectName,
483 &policy->policyRef, hash_size,
484 current_hash_alg,
485 ¤t_digest->digests[digest_idx].digest);
486 goto_if_error(r, "crypto hash start", cleanup);
487
488 cleanup:
489 return r;
490 }
491
492 /** Calculate a policy for for comparing current TPM timers with the policy.
493 *
494 * The timer value and the operation for comparison defined in the policy will
495 * bu used to update the policy digest.
496 * The offset which is supported by the TPM policy for FAPI will be 0.
497 *
498 * @param[in] policy The policy with the timer value and the operation for
499 * comparison.
500 * @param[in,out] current_digest The digest list which has to be updated.
501 * @param[in] current_hash_alg The hash algorithm used for the policy computation.
502 *
503 * @retval TSS2_RC_SUCCESS on success.
504 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
505 * the function.
506 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
507 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
508 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
509 */
510 TSS2_RC
ifapi_calculate_policy_counter_timer(TPMS_POLICYCOUNTERTIMER * policy,TPML_DIGEST_VALUES * current_digest,TPMI_ALG_HASH current_hash_alg)511 ifapi_calculate_policy_counter_timer(
512 TPMS_POLICYCOUNTERTIMER *policy,
513 TPML_DIGEST_VALUES *current_digest,
514 TPMI_ALG_HASH current_hash_alg)
515 {
516 TSS2_RC r = TSS2_RC_SUCCESS;
517 IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext = NULL;
518 size_t digest_idx;
519 size_t hash_size;
520 TPM2B_DIGEST counter_timer_hash;
521
522 LOG_DEBUG("call");
523
524 if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
525 goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
526 "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
527 current_hash_alg);
528 }
529
530 /* Compute of the index of the current policy in the passed digest list */
531 r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
532 return_if_error(r, "Get hash alg for digest.");
533
534 r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
535 return_if_error(r, "crypto hash start");
536
537 /* Compute a has value from the offset, the timer value and the operation. */
538 HASH_UPDATE_BUFFER(cryptoContext, &policy->operandB.buffer[0],
539 policy->operandB.size, r, cleanup);
540 HASH_UPDATE(cryptoContext, UINT16, policy->offset, r, cleanup);
541 HASH_UPDATE(cryptoContext, UINT16, policy->operation, r, cleanup);
542
543 r = ifapi_crypto_hash_finish(&cryptoContext,
544 (uint8_t *) &counter_timer_hash.buffer[0], &hash_size);
545 return_if_error(r, "crypto hash finish");
546
547 /* Extend the policy digest from the hash value computed above and the
548 command code. */
549 r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
550 return_if_error(r, "crypto hash start");
551
552 HASH_UPDATE_BUFFER(cryptoContext,
553 ¤t_digest->digests[digest_idx].digest, hash_size,
554 r, cleanup);
555 HASH_UPDATE(cryptoContext, TPM2_CC, TPM2_CC_PolicyCounterTimer, r, cleanup);
556 HASH_UPDATE_BUFFER(cryptoContext, &counter_timer_hash.buffer[0],
557 hash_size, r, cleanup);
558 r = ifapi_crypto_hash_finish(&cryptoContext,
559 (uint8_t *) ¤t_digest->digests[digest_idx].digest,
560 &hash_size);
561 cleanup:
562 if (cryptoContext)
563 ifapi_crypto_hash_abort(&cryptoContext);
564 return r;
565 }
566
567 /** Update policy if only the command codes are used.
568 *
569 * Some simple policies use onle one or two command codes for policy calculation.
570 *
571 * @param[in] command_code1 The first command code for policy extension.
572 * Can be NULL.
573 * @param[in] command_code2 The second command code for policy extension.
574 * Can be NULL.
575 * @param[in,out] current_digest The digest list which has to be updated.
576 * @param[in] current_hash_alg The hash algorithm used for the policy computation.
577 *
578 * @retval TSS2_RC_SUCCESS on success.
579 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
580 * the function.
581 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
582 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
583 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
584 */
585 TSS2_RC
ifapi_calculate_simple_policy(TPM2_CC command_code1,TPM2_CC command_code2,TPML_DIGEST_VALUES * current_digest,TPMI_ALG_HASH current_hash_alg)586 ifapi_calculate_simple_policy(
587 TPM2_CC command_code1,
588 TPM2_CC command_code2,
589 TPML_DIGEST_VALUES *current_digest,
590 TPMI_ALG_HASH current_hash_alg)
591 {
592 TSS2_RC r = TSS2_RC_SUCCESS;
593 IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext = NULL;
594 size_t digest_idx;
595 size_t hash_size;
596
597 LOG_DEBUG("call");
598
599 if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
600 goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
601 "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
602 current_hash_alg);
603 }
604
605 /* Compute of the index of the current policy in the passed digest list */
606 r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
607 return_if_error(r, "Get hash alg for digest.");
608
609 /* Update the policy */
610 r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
611 return_if_error(r, "crypto hash start");
612
613 HASH_UPDATE_BUFFER(cryptoContext,
614 ¤t_digest->digests[digest_idx].digest, hash_size,
615 r, cleanup);
616 if (command_code1) {
617 HASH_UPDATE(cryptoContext, TPM2_CC, command_code1, r, cleanup);
618 }
619 if (command_code2) {
620 HASH_UPDATE(cryptoContext, TPM2_CC, command_code2, r, cleanup);
621 }
622 r = ifapi_crypto_hash_finish(&cryptoContext,
623 (uint8_t *) ¤t_digest->digests[digest_idx].digest,
624 &hash_size);
625
626 cleanup:
627 if (cryptoContext)
628 ifapi_crypto_hash_abort(&cryptoContext);
629 return r;
630 }
631
632 /** Update policy with command code policy physical presence.
633 *
634 * The policy will be updated with the function ifapi_calculate_simple_policy()
635 *
636 * @param[in] policy The policy physical presence.
637 * @param[in,out] current_digest The digest list which has to be updated.
638 * @param[in] current_hash_alg The hash algorithm used for the policy computation.
639 *
640 * @retval TSS2_RC_SUCCESS on success.
641 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
642 * the function.
643 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
644 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
645 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
646 */
647 TSS2_RC
ifapi_calculate_policy_physical_presence(TPMS_POLICYPHYSICALPRESENCE * policy,TPML_DIGEST_VALUES * current_digest,TPMI_ALG_HASH current_hash_alg)648 ifapi_calculate_policy_physical_presence(
649 TPMS_POLICYPHYSICALPRESENCE *policy,
650 TPML_DIGEST_VALUES *current_digest,
651 TPMI_ALG_HASH current_hash_alg)
652 {
653 TSS2_RC r = TSS2_RC_SUCCESS;
654 (void)policy;
655
656 LOG_DEBUG("call");
657
658 r = ifapi_calculate_simple_policy(TPM2_CC_PolicyPhysicalPresence, 0,
659 current_digest, current_hash_alg);
660 return_if_error(r, "Calculate policy for command code.");
661
662 return r;
663 }
664
665 /** Update policy with command code of policy auth value.
666 *
667 * The policy will be updated with the function ifapi_calculate_simple_policy()
668 *
669 * @param[in] policy The policy auth value.
670 * @param[in,out] current_digest The digest list which has to be updated.
671 * @param[in] current_hash_alg The hash algorithm used for the policy computation.
672 *
673 * @retval TSS2_RC_SUCCESS on success.
674 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
675 * the function.
676 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
677 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
678 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
679 */
680 TSS2_RC
ifapi_calculate_policy_auth_value(TPMS_POLICYAUTHVALUE * policy,TPML_DIGEST_VALUES * current_digest,TPMI_ALG_HASH current_hash_alg)681 ifapi_calculate_policy_auth_value(
682 TPMS_POLICYAUTHVALUE *policy,
683 TPML_DIGEST_VALUES *current_digest,
684 TPMI_ALG_HASH current_hash_alg)
685 {
686 TSS2_RC r = TSS2_RC_SUCCESS;
687 (void)policy;
688
689 LOG_DEBUG("call");
690
691 r = ifapi_calculate_simple_policy(TPM2_CC_PolicyAuthValue, 0,
692 current_digest, current_hash_alg);
693 return_if_error(r, "Calculate policy auth value.");
694
695 return r;
696 }
697
698 /** Update policy with the command code of policy password.
699 *
700 * The policy will be updated with the function ifapi_calculate_simple_policy()
701 *
702 * @param[in] policy The policy password.
703 * @param[in,out] current_digest The digest list which has to be updated.
704 * @param[in] current_hash_alg The hash algorithm used for the policy computation.
705 *
706 * @retval TSS2_RC_SUCCESS on success.
707 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
708 * the function.
709 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
710 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
711 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
712 */
713 TSS2_RC
ifapi_calculate_policy_password(TPMS_POLICYPASSWORD * policy,TPML_DIGEST_VALUES * current_digest,TPMI_ALG_HASH current_hash_alg)714 ifapi_calculate_policy_password(
715 TPMS_POLICYPASSWORD *policy,
716 TPML_DIGEST_VALUES *current_digest,
717 TPMI_ALG_HASH current_hash_alg)
718 {
719 TSS2_RC r = TSS2_RC_SUCCESS;
720 (void)policy;
721
722 LOG_DEBUG("call");
723
724 r = ifapi_calculate_simple_policy(TPM2_CC_PolicyAuthValue, 0,
725 current_digest, current_hash_alg);
726 return_if_error(r, "Calculate policy password.");
727
728 return r;
729 }
730
731 /** Update policy command code with a command code defined in the policy.
732 *
733 * For the update two command codes will be used. The command code of
734 * policy command code and the passed command code.
735 * The policy will be updated with the function ifapi_calculate_simple_policy()
736 *
737 * @param[in] policy The policy command code with the second command code.
738 * @param[in,out] current_digest The digest list which has to be updated.
739 * @param[in] current_hash_alg The hash algorithm used for the policy computation.
740 *
741 * @retval TSS2_RC_SUCCESS on success.
742 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
743 * the function.
744 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
745 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
746 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
747 */
748 TSS2_RC
ifapi_calculate_policy_command_code(TPMS_POLICYCOMMANDCODE * policy,TPML_DIGEST_VALUES * current_digest,TPMI_ALG_HASH current_hash_alg)749 ifapi_calculate_policy_command_code(
750 TPMS_POLICYCOMMANDCODE *policy,
751 TPML_DIGEST_VALUES *current_digest,
752 TPMI_ALG_HASH current_hash_alg)
753 {
754 TSS2_RC r = TSS2_RC_SUCCESS;
755
756 LOG_DEBUG("call");
757
758 r = ifapi_calculate_simple_policy(TPM2_CC_PolicyCommandCode, policy->code,
759 current_digest, current_hash_alg);
760 return_if_error(r, "Calculate policy for command code.");
761
762 return r;
763 }
764
765 /** Compute policy if only a digest and a command code are needed for extension.
766 *
767 * @param[in] digest the digest which will be used for policy extension.
768 * @param[in,out] current_digest The digest list which has to be updated.
769 * @param[in] current_hash_alg The hash algorithm used for the policy computation.
770 * @param[in] command_code The compute of the command which did compute the digest.
771 *
772 * @retval TSS2_RC_SUCCESS on success.
773 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
774 * the function.
775 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
776 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
777 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
778 */
779 TSS2_RC
ifapi_calculate_policy_digest_hash(TPM2B_DIGEST * digest,TPML_DIGEST_VALUES * current_digest,TPMI_ALG_HASH current_hash_alg,TPM2_CC command_code)780 ifapi_calculate_policy_digest_hash(
781 TPM2B_DIGEST *digest,
782 TPML_DIGEST_VALUES *current_digest,
783 TPMI_ALG_HASH current_hash_alg,
784 TPM2_CC command_code)
785 {
786 TSS2_RC r = TSS2_RC_SUCCESS;
787 IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext = NULL;
788 size_t digest_idx;
789 size_t hash_size;
790
791 LOG_DEBUG("call");
792
793 if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
794 goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
795 "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
796 current_hash_alg);
797 }
798
799 /* Compute of the index of the current policy in the passed digest list */
800 r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
801 return_if_error(r, "Get hash alg for digest.");
802
803 /* Update the policy. */
804 r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
805 return_if_error(r, "crypto hash start");
806
807 HASH_UPDATE_BUFFER(cryptoContext,
808 ¤t_digest->digests[digest_idx].digest, hash_size,
809 r, cleanup);
810 HASH_UPDATE(cryptoContext, TPM2_CC, command_code, r, cleanup);
811 HASH_UPDATE_BUFFER(cryptoContext, &digest->buffer[0],
812 digest->size, r, cleanup);
813 r = ifapi_crypto_hash_finish(&cryptoContext,
814 (uint8_t *) ¤t_digest->digests[digest_idx].digest,
815 &hash_size);
816 cleanup:
817 if (cryptoContext)
818 ifapi_crypto_hash_abort(&cryptoContext);
819 return r;
820 }
821
822 /** Compute policy bound to a specific set of TPM entities.
823 *
824 * The policy digest will be updated with the function
825 * ifapi_calculate_policy_digest_hash() which will add the hash of the
826 * entity name list.
827 *
828 * @param[in] policy The policy with the list of entity names.
829 * @param[in,out] current_digest The digest list which has to be updated.
830 * @param[in] current_hash_alg The hash algorithm used for the policy computation.
831 *
832 * @retval TSS2_RC_SUCCESS on success.
833 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
834 * the function.
835 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
836 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
837 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
838 */
839 TSS2_RC
ifapi_calculate_policy_name_hash(TPMS_POLICYNAMEHASH * policy,TPML_DIGEST_VALUES * current_digest,TPMI_ALG_HASH current_hash_alg)840 ifapi_calculate_policy_name_hash(
841 TPMS_POLICYNAMEHASH *policy,
842 TPML_DIGEST_VALUES *current_digest,
843 TPMI_ALG_HASH current_hash_alg)
844 {
845 TSS2_RC r = TSS2_RC_SUCCESS;
846 IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext = NULL;
847 size_t hash_size;
848 size_t i;
849
850 LOG_DEBUG("call");
851
852 if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
853 goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
854 "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
855 current_hash_alg);
856 }
857
858 /* Compute of the index of the current policy in the passed digest list */
859 r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
860 return_if_error(r, "crypto hash start");
861
862 /* Compute name hash from the list of object names */
863 for (i = 0; i <= policy->count; i++) {
864 HASH_UPDATE_BUFFER(cryptoContext, &policy->objectNames[i].name[0],
865 policy->objectNames[i].size, r,
866 cleanup);
867 }
868 r = ifapi_crypto_hash_finish(&cryptoContext,
869 (uint8_t *) &policy->nameHash.buffer[0],
870 &hash_size);
871 return_if_error(r, "crypto hash finish");
872
873 policy->nameHash.size = hash_size;
874
875 /* Update the policy with the computed hash value of the name list and
876 the command code. */
877 r = ifapi_calculate_policy_digest_hash(&policy->nameHash,
878 current_digest,
879 current_hash_alg, TPM2_CC_PolicyNameHash);
880 return_if_error(r, "Calculate digest hash for policy");
881
882 cleanup:
883 if (cryptoContext)
884 ifapi_crypto_hash_abort(&cryptoContext);
885 return r;
886 }
887
888 /** Compute policy bound to a specific command and command parameters.
889 *
890 * The cp hash value and the command code will be updated by the
891 * function ifapi_calculate_policy_digest_hash().
892 *
893 * @param[in] policy The policy with the cp hash value.
894 * @param[in,out] current_digest The digest list which has to be updated.
895 * @param[in] current_hash_alg The hash algorithm used for the policy computation.
896 *
897 * @retval TSS2_RC_SUCCESS on success.
898 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
899 * the function.
900 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
901 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
902 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
903 */
904 TSS2_RC
ifapi_calculate_policy_cp_hash(TPMS_POLICYCPHASH * policy,TPML_DIGEST_VALUES * current_digest,TPMI_ALG_HASH current_hash_alg)905 ifapi_calculate_policy_cp_hash(
906 TPMS_POLICYCPHASH *policy,
907 TPML_DIGEST_VALUES *current_digest,
908 TPMI_ALG_HASH current_hash_alg)
909 {
910 TSS2_RC r = TSS2_RC_SUCCESS;
911
912 LOG_DEBUG("call");
913
914 r = ifapi_calculate_policy_digest_hash(&policy->cpHash,
915 current_digest, current_hash_alg,
916 TPM2_CC_PolicyCpHash);
917 return_if_error(r, "Calculate digest hash for policy");
918
919 return r;
920 }
921
922 /** Compute policy which limits authorization to a specific locality.
923 *
924 * @param[in] policy The policy with the locality.
925 * @param[in,out] current_digest The digest list which has to be updated.
926 * @param[in] current_hash_alg The hash algorithm used for the policy computation.
927 *
928 * @retval TSS2_RC_SUCCESS on success.
929 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
930 * the function.
931 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
932 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
933 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
934 */
935 TSS2_RC
ifapi_calculate_policy_locality(TPMS_POLICYLOCALITY * policy,TPML_DIGEST_VALUES * current_digest,TPMI_ALG_HASH current_hash_alg)936 ifapi_calculate_policy_locality(
937 TPMS_POLICYLOCALITY *policy,
938 TPML_DIGEST_VALUES *current_digest,
939 TPMI_ALG_HASH current_hash_alg)
940 {
941 TSS2_RC r = TSS2_RC_SUCCESS;
942 IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext = NULL;
943 size_t digest_idx;
944 size_t hash_size;
945
946 LOG_DEBUG("call");
947
948 if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
949 goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
950 "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
951 current_hash_alg);
952 }
953
954 /* Compute of the index of the current policy in the passed digest list */
955 r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
956 return_if_error(r, "Get hash alg for digest.");
957
958 /* Update the policy */
959 r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
960 return_if_error(r, "crypto hash start");
961
962 HASH_UPDATE_BUFFER(cryptoContext,
963 ¤t_digest->digests[digest_idx].digest, hash_size,
964 r, cleanup);
965 HASH_UPDATE(cryptoContext, TPM2_CC, TPM2_CC_PolicyLocality, r, cleanup);
966 HASH_UPDATE(cryptoContext, BYTE, policy->locality, r, cleanup);
967 r = ifapi_crypto_hash_finish(&cryptoContext,
968 (uint8_t *) & current_digest->
969 digests[digest_idx].digest, &hash_size);
970
971 cleanup:
972 if (cryptoContext)
973 ifapi_crypto_hash_abort(&cryptoContext);
974 return r;
975 }
976
977 /** Compute policy bound to bound to the TPMA_NV_WRITTEN attributes.
978 *
979 * The expected value of the NV written attribute is part of the policy.
980 *
981 * @param[in] policy The policy with the expected attribute value.
982 * @param[in,out] current_digest The digest list which has to be updated.
983 * @param[in] current_hash_alg The hash algorithm used for the policy computation.
984 *
985 * @retval TSS2_RC_SUCCESS on success.
986 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
987 * the function.
988 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
989 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
990 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
991 */
992 TSS2_RC
ifapi_calculate_policy_nv_written(TPMS_POLICYNVWRITTEN * policy,TPML_DIGEST_VALUES * current_digest,TPMI_ALG_HASH current_hash_alg)993 ifapi_calculate_policy_nv_written(
994 TPMS_POLICYNVWRITTEN *policy,
995 TPML_DIGEST_VALUES *current_digest,
996 TPMI_ALG_HASH current_hash_alg)
997 {
998 TSS2_RC r = TSS2_RC_SUCCESS;
999 IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext = NULL;
1000 size_t digest_idx;
1001 size_t hash_size;
1002
1003 LOG_DEBUG("call");
1004
1005 if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
1006 goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
1007 "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
1008 current_hash_alg);
1009 }
1010
1011 /* Compute of the index of the current policy in the passed digest list */
1012 r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
1013 return_if_error(r, "Get hash alg for digest.");
1014
1015 /* Update the policy */
1016 r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
1017 return_if_error(r, "crypto hash start");
1018
1019 HASH_UPDATE_BUFFER(cryptoContext,
1020 ¤t_digest->digests[digest_idx].digest, hash_size,
1021 r, cleanup);
1022 HASH_UPDATE(cryptoContext, TPM2_CC, TPM2_CC_PolicyNvWritten, r, cleanup);
1023 /* Update the expected attribute value. */
1024 HASH_UPDATE(cryptoContext, BYTE, policy->writtenSet, r, cleanup);
1025 r = ifapi_crypto_hash_finish(&cryptoContext,
1026 (uint8_t *) & current_digest->
1027 digests[digest_idx].digest, &hash_size);
1028
1029 cleanup:
1030 if (cryptoContext)
1031 ifapi_crypto_hash_abort(&cryptoContext);
1032 return r;
1033 }
1034
1035 /** Compute policy bound to the content of an NV index.
1036 *
1037 * The value used for comparison, the compare operation and an
1038 * offset for the NV index are part of the policy.
1039 *
1040 * @param[in] policy The policy with the expected values used for comparison.
1041 * @param[in,out] current_digest The digest list which has to be updated.
1042 * @param[in] current_hash_alg The hash algorithm used for the policy computation.
1043 *
1044 * @retval TSS2_RC_SUCCESS on success.
1045 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
1046 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1047 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1048 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
1049 * the function.
1050 */
1051 TSS2_RC
ifapi_calculate_policy_nv(TPMS_POLICYNV * policy,TPML_DIGEST_VALUES * current_digest,TPMI_ALG_HASH current_hash_alg)1052 ifapi_calculate_policy_nv(
1053 TPMS_POLICYNV *policy,
1054 TPML_DIGEST_VALUES *current_digest,
1055 TPMI_ALG_HASH current_hash_alg)
1056 {
1057 TSS2_RC r = TSS2_RC_SUCCESS;
1058 IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext = NULL;
1059 TPM2B_NAME nv_name;
1060 size_t hash_size;
1061 TPM2B_DIGEST nv_hash;
1062 size_t digest_idx;
1063
1064 LOG_DEBUG("call");
1065
1066 memset(&nv_name, 0, sizeof(TPM2B_NAME));
1067
1068 /* Compute NV name from public info */
1069
1070 r = ifapi_nv_get_name(&policy->nvPublic, &nv_name);
1071 return_if_error(r, "Compute NV name");
1072
1073 /* Compute of the index of the current policy in the passed digest list */
1074 r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
1075 return_if_error(r, "Get hash alg for digest.");
1076
1077 r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
1078 return_if_error(r, "crypto hash start");
1079
1080 /* Compute the hash for the compare operation. */
1081 HASH_UPDATE_BUFFER(cryptoContext, &policy->operandB.buffer[0],
1082 policy->operandB.size, r, cleanup);
1083 HASH_UPDATE(cryptoContext, UINT16, policy->offset, r, cleanup);
1084 HASH_UPDATE(cryptoContext, UINT16, policy->operation, r, cleanup);
1085 r = ifapi_crypto_hash_finish(&cryptoContext,
1086 (uint8_t *) &nv_hash.buffer[0], &hash_size);
1087 return_if_error(r, "crypto hash finish");
1088
1089 nv_hash.size = hash_size;
1090
1091 /* Update the policy with the hash of the compare operation and the NV name. */
1092 r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
1093 return_if_error(r, "crypto hash start");
1094
1095 HASH_UPDATE_BUFFER(cryptoContext,
1096 ¤t_digest->digests[digest_idx].digest, hash_size,
1097 r, cleanup);
1098 HASH_UPDATE(cryptoContext, TPM2_CC, TPM2_CC_PolicyNV, r, cleanup);
1099 HASH_UPDATE_BUFFER(cryptoContext, &nv_hash.buffer[0], nv_hash.size, r, cleanup)
1100 HASH_UPDATE_BUFFER(cryptoContext, &nv_name.name[0], nv_name.size, r, cleanup);
1101 r = ifapi_crypto_hash_finish(&cryptoContext,
1102 (uint8_t *) ¤t_digest->digests[digest_idx].digest,
1103 &hash_size);
1104 return_if_error(r, "crypto hash finish");
1105
1106 cleanup:
1107 if (cryptoContext)
1108 ifapi_crypto_hash_abort(&cryptoContext);
1109 return r;
1110 }
1111
1112 /** Compute a list of policies to enable authorization options.
1113 *
1114 * First the policy digest will be computed for every branch.
1115 * After that the policy digest will be reset to zero and extended by the
1116 * list of computed policy digests of the branches.
1117 *
1118 * @param[in] policyOr The policy with the possible policy branches.
1119 * @param[in,out] current_digest The digest list which has to be updated.
1120 * @param[in] hash_alg The hash algorithm used for the policy computation.
1121 * @param[in] hash_size The size of the policy digest.
1122 * @param[in] digest_idx The index of the current policy in the passed digest list.
1123 *
1124 * @retval TSS2_RC_SUCCESS on success.
1125 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
1126 * the function.
1127 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
1128 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1129 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1130 */
1131 TSS2_RC
ifapi_calculate_policy_or(TPMS_POLICYOR * policyOr,TPML_DIGEST_VALUES * current_digest,TPMI_ALG_HASH hash_alg,size_t hash_size,size_t digest_idx)1132 ifapi_calculate_policy_or(
1133 TPMS_POLICYOR *policyOr,
1134 TPML_DIGEST_VALUES *current_digest,
1135 TPMI_ALG_HASH hash_alg,
1136 size_t hash_size,
1137 size_t digest_idx)
1138 {
1139 size_t i;
1140 TSS2_RC r = TSS2_RC_SUCCESS;
1141 IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext = NULL;
1142
1143 for (i = 0; i < policyOr->branches->count; i++) {
1144 /* Compute the policy digest for every branch. */
1145 copy_policy_digest(&policyOr->branches->authorizations[i].policyDigests,
1146 current_digest, digest_idx, hash_size,
1147 "Copy or digest");
1148
1149 r = ifapi_calculate_policy(policyOr->branches->authorizations[i].policy,
1150 &policyOr->branches->authorizations[i].
1151 policyDigests, hash_alg, hash_size,
1152 digest_idx);
1153 log_policy_digest(&policyOr->branches->authorizations[i].policyDigests,
1154 digest_idx, hash_size, "Branch digest");
1155
1156 return_if_error(r, "Compute policy.");
1157 }
1158 /* Reset the or policy digest because the digest is included in all sub policies */
1159 memset(¤t_digest->digests[digest_idx], 0, hash_size);
1160 r = ifapi_crypto_hash_start(&cryptoContext, hash_alg);
1161 return_if_error(r, "crypto hash start");
1162 r = ifapi_crypto_hash_update(cryptoContext, (const uint8_t *)
1163 ¤t_digest->digests[digest_idx].digest,
1164 hash_size);
1165 goto_if_error(r, "crypto hash update", cleanup);
1166
1167 /* Start with the update of the reset digest. */
1168 uint8_t buffer[sizeof(TPM2_CC)];
1169 size_t offset = 0;
1170 r = Tss2_MU_TPM2_CC_Marshal(TPM2_CC_PolicyOR,
1171 &buffer[0], sizeof(TPM2_CC), &offset);
1172 goto_if_error(r, "Marshal cc", cleanup);
1173
1174 r = ifapi_crypto_hash_update(cryptoContext,
1175 (const uint8_t *)&buffer[0], sizeof(TPM2_CC));
1176 goto_if_error(r, "crypto hash update", cleanup);
1177
1178 /* Update the digest with the complete list of computed digests of the branches. */
1179 for (i = 0; i < policyOr->branches->count; i++) {
1180 r = ifapi_crypto_hash_update(cryptoContext, (const uint8_t *)
1181 &policyOr->branches->authorizations[i]
1182 .policyDigests.digests[digest_idx].digest,
1183 hash_size);
1184 log_policy_digest(&policyOr->branches->authorizations[i].policyDigests,
1185 digest_idx, hash_size, "Or branch");
1186 current_digest->count =
1187 policyOr->branches->authorizations[i].policyDigests.count;
1188 goto_if_error(r, "crypto hash update", cleanup);
1189 }
1190 current_digest->digests[digest_idx].hashAlg = hash_alg;
1191 r = ifapi_crypto_hash_finish(&cryptoContext,
1192 (uint8_t *) & current_digest->
1193 digests[digest_idx].digest, &hash_size);
1194 log_policy_digest(current_digest, digest_idx, hash_size, "Final or digest");
1195 goto_if_error(r, "crypto hash finish", cleanup);
1196
1197 cleanup:
1198 if (cryptoContext)
1199 ifapi_crypto_hash_abort(&cryptoContext);
1200 return r;
1201 }
1202
1203 /** Compute policy digest for a list of policies.
1204 *
1205 * Every policy in the list will update the previous policy. Thus the final
1206 * policy digest will describe the sequential execution of the policy list.
1207 *
1208 * @param[in] policy The policy with the policy list.
1209 * @param[in,out] policyDigests The digest list which has to be updated.
1210 * @param[in] hash_alg The hash algorithm used for the policy computation.
1211 * @param[in] hash_size The size of the policy digest.
1212 * @param[in] digest_idx The index of the current policy in the passed digest list.
1213 *
1214 * @retval TSS2_RC_SUCCESS on success.
1215 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
1216 * the function.
1217 * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
1218 * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1219 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1220 */
1221 TSS2_RC
ifapi_calculate_policy(TPML_POLICYELEMENTS * policy,TPML_DIGEST_VALUES * policyDigests,TPMI_ALG_HASH hash_alg,size_t hash_size,size_t digest_idx)1222 ifapi_calculate_policy(
1223 TPML_POLICYELEMENTS *policy,
1224 TPML_DIGEST_VALUES *policyDigests,
1225 TPMI_ALG_HASH hash_alg,
1226 size_t hash_size,
1227 size_t digest_idx)
1228 {
1229 size_t i;
1230 TSS2_RC r = TSS2_RC_SUCCESS;
1231
1232 for (i = 0; i < policy->count; i++) {
1233
1234 copy_policy_digest(&policy->elements[i].policyDigests,
1235 policyDigests, digest_idx, hash_size,
1236 "Copy policy digest (to)");
1237
1238 switch (policy->elements[i].type) {
1239
1240 case POLICYPCR:
1241 r = ifapi_compute_policy_pcr(&policy->elements[i].element.PolicyPCR,
1242 &policy->elements[i].policyDigests,
1243 hash_alg);
1244 return_if_error(r, "Compute policy pcr");
1245 break;
1246
1247 case POLICYSIGNED:
1248 r = ifapi_calculate_policy_signed(&policy->elements[i].element.
1249 PolicySigned,
1250 &policy->elements[i].
1251 policyDigests, hash_alg);
1252 return_if_error(r, "Compute policy nv");
1253
1254 break;
1255
1256 case POLICYDUPLICATIONSELECT:
1257 r = ifapi_calculate_policy_duplicate(&policy->elements[i].element.
1258 PolicyDuplicationSelect,
1259 &policy->elements[i].
1260 policyDigests, hash_alg);
1261 return_if_error(r, "Compute policy duplication select");
1262
1263 break;
1264
1265 case POLICYAUTHORIZENV:
1266 r = ifapi_calculate_policy_authorize_nv(&policy->elements[i].
1267 element.PolicyAuthorizeNv,
1268 &policy->elements[i].
1269 policyDigests, hash_alg);
1270 return_if_error(r, "Compute policy authorizeg");
1271
1272 break;
1273
1274 case POLICYAUTHORIZE:
1275 r = ifapi_calculate_policy_authorize(&policy->elements[i].element.
1276 PolicyAuthorize,
1277 &policy->elements[i].
1278 policyDigests, hash_alg);
1279 return_if_error(r, "Compute policy authorizeg");
1280
1281 break;
1282
1283 case POLICYSECRET:
1284 r = ifapi_calculate_policy_secret(&policy->elements[i].element.
1285 PolicySecret,
1286 &policy->elements[i].
1287 policyDigests, hash_alg);
1288 return_if_error(r, "Compute policy nv");
1289
1290 break;
1291
1292 case POLICYOR:
1293 r = ifapi_calculate_policy_or(&policy->elements[i].element.PolicyOr,
1294 &policy->elements[i].policyDigests,
1295 hash_alg, hash_size, digest_idx);
1296 return_if_error(r, "Compute policy or");
1297
1298 break;
1299
1300 case POLICYNV:
1301 r = ifapi_calculate_policy_nv(&policy->elements[i].element.PolicyNV,
1302 &policy->elements[i].policyDigests,
1303 hash_alg);
1304 return_if_error(r, "Compute policy nv");
1305
1306 break;
1307
1308 case POLICYNVWRITTEN:
1309 r = ifapi_calculate_policy_nv_written(&policy->elements[i].element.
1310 PolicyNvWritten,
1311 &policy->elements[i].
1312 policyDigests, hash_alg);
1313 return_if_error(r, "Compute policy nv written");
1314 break;
1315
1316 case POLICYCOUNTERTIMER:
1317 r = ifapi_calculate_policy_counter_timer(
1318 &policy->elements[i].element.PolicyCounterTimer,
1319 &policy->elements[i].policyDigests, hash_alg);
1320 return_if_error(r, "Compute policy counter timer");
1321 break;
1322
1323 case POLICYPHYSICALPRESENCE:
1324 r = ifapi_calculate_policy_physical_presence(
1325 &policy->elements[i].element.PolicyPhysicalPresence,
1326 &policy->elements[i].policyDigests, hash_alg);
1327 return_if_error(r, "Compute policy physical presence");
1328 break;
1329
1330 case POLICYAUTHVALUE:
1331 r = ifapi_calculate_policy_auth_value(&policy->elements[i].element.PolicyAuthValue,
1332 &policy->elements[i].policyDigests, hash_alg);
1333 return_if_error(r, "Compute policy auth value");
1334 break;
1335
1336 case POLICYPASSWORD:
1337 r = ifapi_calculate_policy_password(&policy->elements[i].element.PolicyPassword,
1338 &policy->elements[i].policyDigests, hash_alg);
1339 return_if_error(r, "Compute policy password");
1340 break;
1341
1342 case POLICYCOMMANDCODE:
1343 r = ifapi_calculate_policy_command_code(&policy->elements[i].element.PolicyCommandCode,
1344 &policy->elements[i].policyDigests, hash_alg);
1345 return_if_error(r, "Compute policy physical presence");
1346 break;
1347
1348 case POLICYNAMEHASH:
1349 r = ifapi_calculate_policy_name_hash(&policy->elements[i].element.PolicyNameHash,
1350 &policy->elements[i].policyDigests, hash_alg);
1351 return_if_error(r, "Compute policy name hash");
1352 break;
1353
1354 case POLICYCPHASH:
1355 r = ifapi_calculate_policy_cp_hash(&policy->elements[i].element.PolicyCpHash,
1356 &policy->elements[i].policyDigests, hash_alg);
1357 return_if_error(r, "Compute policy cp hash");
1358 break;
1359
1360 case POLICYLOCALITY:
1361 r = ifapi_calculate_policy_locality(&policy->elements[i].element.PolicyLocality,
1362 &policy->elements[i].policyDigests, hash_alg);
1363 return_if_error(r, "Compute policy locality");
1364 break;
1365
1366 case POLICYACTION:
1367 /* This does not alter the policyDigest */
1368 break;
1369
1370 default:
1371 return_error(TSS2_FAPI_RC_BAD_VALUE,
1372 "Policy not implemented");
1373 }
1374
1375 copy_policy_digest(policyDigests, &policy->elements[i].policyDigests,
1376 digest_idx, hash_size, "Copy policy digest (from)");
1377 }
1378 return r;
1379 }
1380