xref: /aosp_15_r20/external/tpm2-tss/src/tss2-fapi/ifapi_policy_calculate.c (revision 758e9fba6fc9adbf15340f70c73baee7b168b1c9)
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                        &current_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                                    &current_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                                    &current_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                        &current_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                                    &current_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                                    &current_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                        &current_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 *) &current_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                        &current_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 *) &current_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                        &current_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 *) &current_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                        &current_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                        &current_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                        &current_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 *) &current_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(&current_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                                  &current_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