xref: /aosp_15_r20/external/tpm2-tss/src/tss2-esys/esys_iutil.c (revision 758e9fba6fc9adbf15340f70c73baee7b168b1c9)
1*758e9fbaSOystein Eftevaag /* SPDX-License-Identifier: BSD-2-Clause */
2*758e9fbaSOystein Eftevaag /*******************************************************************************
3*758e9fbaSOystein Eftevaag  * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
4*758e9fbaSOystein Eftevaag  * All rights reserved.
5*758e9fbaSOystein Eftevaag  ******************************************************************************/
6*758e9fbaSOystein Eftevaag #ifdef HAVE_CONFIG_H
7*758e9fbaSOystein Eftevaag #include <config.h>
8*758e9fbaSOystein Eftevaag #endif
9*758e9fbaSOystein Eftevaag 
10*758e9fbaSOystein Eftevaag #include <inttypes.h>
11*758e9fbaSOystein Eftevaag 
12*758e9fbaSOystein Eftevaag #include "tss2_esys.h"
13*758e9fbaSOystein Eftevaag #include "esys_mu.h"
14*758e9fbaSOystein Eftevaag 
15*758e9fbaSOystein Eftevaag #include "esys_iutil.h"
16*758e9fbaSOystein Eftevaag #include "esys_int.h"
17*758e9fbaSOystein Eftevaag #define LOGMODULE esys
18*758e9fbaSOystein Eftevaag #include "util/log.h"
19*758e9fbaSOystein Eftevaag #include "util/aux_util.h"
20*758e9fbaSOystein Eftevaag 
21*758e9fbaSOystein Eftevaag /**
22*758e9fbaSOystein Eftevaag  * Compare variables of type UINT16.
23*758e9fbaSOystein Eftevaag  * @param[in] in1 Variable to be compared with:
24*758e9fbaSOystein Eftevaag  * @param[in] in2
25*758e9fbaSOystein Eftevaag  */
26*758e9fbaSOystein Eftevaag static bool
cmp_UINT16(const UINT16 * in1,const UINT16 * in2)27*758e9fbaSOystein Eftevaag cmp_UINT16(const UINT16 * in1, const UINT16 * in2)
28*758e9fbaSOystein Eftevaag {
29*758e9fbaSOystein Eftevaag     LOG_TRACE("call");
30*758e9fbaSOystein Eftevaag     if (*in1 == *in2)
31*758e9fbaSOystein Eftevaag         return true;
32*758e9fbaSOystein Eftevaag     else {
33*758e9fbaSOystein Eftevaag         LOG_TRACE("cmp false");
34*758e9fbaSOystein Eftevaag         return false;
35*758e9fbaSOystein Eftevaag     }
36*758e9fbaSOystein Eftevaag }
37*758e9fbaSOystein Eftevaag 
38*758e9fbaSOystein Eftevaag /**
39*758e9fbaSOystein Eftevaag  * Compare two arrays of type BYTE.
40*758e9fbaSOystein Eftevaag  * @param[in] in1 array to be compared with:.
41*758e9fbaSOystein Eftevaag  * @param[in] in2
42*758e9fbaSOystein Eftevaag  */
43*758e9fbaSOystein Eftevaag 
44*758e9fbaSOystein Eftevaag static bool
cmp_BYTE_array(const BYTE * in1,size_t count1,const BYTE * in2,size_t count2)45*758e9fbaSOystein Eftevaag cmp_BYTE_array(const BYTE * in1, size_t count1, const BYTE * in2, size_t count2)
46*758e9fbaSOystein Eftevaag {
47*758e9fbaSOystein Eftevaag     if (count1 != count2) {
48*758e9fbaSOystein Eftevaag         LOG_TRACE("cmp false");
49*758e9fbaSOystein Eftevaag         return false;
50*758e9fbaSOystein Eftevaag     }
51*758e9fbaSOystein Eftevaag 
52*758e9fbaSOystein Eftevaag     if (memcmp(in1, in2, count2) != 0) {
53*758e9fbaSOystein Eftevaag         LOG_TRACE("cmp false");
54*758e9fbaSOystein Eftevaag         return false;
55*758e9fbaSOystein Eftevaag     }
56*758e9fbaSOystein Eftevaag 
57*758e9fbaSOystein Eftevaag     return true;
58*758e9fbaSOystein Eftevaag }
59*758e9fbaSOystein Eftevaag 
60*758e9fbaSOystein Eftevaag /**
61*758e9fbaSOystein Eftevaag  * Compare two variables of type TPM2B_DIGEST.
62*758e9fbaSOystein Eftevaag  * @param[in] in1 variable to be compared with:
63*758e9fbaSOystein Eftevaag  * @param[in] in2
64*758e9fbaSOystein Eftevaag  */
65*758e9fbaSOystein Eftevaag static bool
cmp_TPM2B_DIGEST(const TPM2B_DIGEST * in1,const TPM2B_DIGEST * in2)66*758e9fbaSOystein Eftevaag cmp_TPM2B_DIGEST(const TPM2B_DIGEST * in1, const TPM2B_DIGEST * in2)
67*758e9fbaSOystein Eftevaag {
68*758e9fbaSOystein Eftevaag     LOG_TRACE("call");
69*758e9fbaSOystein Eftevaag 
70*758e9fbaSOystein Eftevaag     if (!cmp_UINT16(&in1->size, &in2->size)) {
71*758e9fbaSOystein Eftevaag         LOG_TRACE("cmp false");
72*758e9fbaSOystein Eftevaag         return false;
73*758e9fbaSOystein Eftevaag     }
74*758e9fbaSOystein Eftevaag 
75*758e9fbaSOystein Eftevaag     return cmp_BYTE_array((BYTE *) & in1->buffer, in1->size,
76*758e9fbaSOystein Eftevaag                           (BYTE *) & in2->buffer, in2->size);
77*758e9fbaSOystein Eftevaag 
78*758e9fbaSOystein Eftevaag     return true;
79*758e9fbaSOystein Eftevaag }
80*758e9fbaSOystein Eftevaag 
81*758e9fbaSOystein Eftevaag /**
82*758e9fbaSOystein Eftevaag  * Compare two variables of type TPM2B_NAME.
83*758e9fbaSOystein Eftevaag  * @param[in] in1 variable to be compared with:
84*758e9fbaSOystein Eftevaag  * @param[in] in2
85*758e9fbaSOystein Eftevaag  */
86*758e9fbaSOystein Eftevaag static bool
cmp_TPM2B_NAME(const TPM2B_NAME * in1,const TPM2B_NAME * in2)87*758e9fbaSOystein Eftevaag cmp_TPM2B_NAME(const TPM2B_NAME * in1, const TPM2B_NAME * in2)
88*758e9fbaSOystein Eftevaag {
89*758e9fbaSOystein Eftevaag     LOG_TRACE("call");
90*758e9fbaSOystein Eftevaag 
91*758e9fbaSOystein Eftevaag     if (!cmp_UINT16(&in1->size, &in2->size)) {
92*758e9fbaSOystein Eftevaag         LOG_TRACE("cmp false");
93*758e9fbaSOystein Eftevaag         return false;
94*758e9fbaSOystein Eftevaag     }
95*758e9fbaSOystein Eftevaag 
96*758e9fbaSOystein Eftevaag     return cmp_BYTE_array((BYTE *) & in1->name, in1->size, (BYTE *) & in2->name,
97*758e9fbaSOystein Eftevaag                           in2->size);
98*758e9fbaSOystein Eftevaag 
99*758e9fbaSOystein Eftevaag     return true;
100*758e9fbaSOystein Eftevaag }
101*758e9fbaSOystein Eftevaag 
102*758e9fbaSOystein Eftevaag /**
103*758e9fbaSOystein Eftevaag  * Compare two structures of type TPM2B_AUTH.
104*758e9fbaSOystein Eftevaag  * @param[in] in1 Structure to be compared with:
105*758e9fbaSOystein Eftevaag  * @param[in] in1
106*758e9fbaSOystein Eftevaag  */
107*758e9fbaSOystein Eftevaag static bool
cmp_TPM2B_AUTH(const TPM2B_AUTH * in1,const TPM2B_AUTH * in2)108*758e9fbaSOystein Eftevaag cmp_TPM2B_AUTH(const TPM2B_AUTH * in1, const TPM2B_AUTH * in2)
109*758e9fbaSOystein Eftevaag {
110*758e9fbaSOystein Eftevaag     LOG_TRACE("call");
111*758e9fbaSOystein Eftevaag     return cmp_TPM2B_DIGEST(in1, in2);
112*758e9fbaSOystein Eftevaag }
113*758e9fbaSOystein Eftevaag 
114*758e9fbaSOystein Eftevaag TSS2_RC
init_session_tab(ESYS_CONTEXT * esys_context,ESYS_TR shandle1,ESYS_TR shandle2,ESYS_TR shandle3)115*758e9fbaSOystein Eftevaag init_session_tab(ESYS_CONTEXT *esys_context,
116*758e9fbaSOystein Eftevaag                  ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3)
117*758e9fbaSOystein Eftevaag {
118*758e9fbaSOystein Eftevaag     TSS2_RC r = TPM2_RC_SUCCESS;
119*758e9fbaSOystein Eftevaag     ESYS_TR handle_tab[3] = { shandle1, shandle2, shandle3 };
120*758e9fbaSOystein Eftevaag     for (int i = 0; i < 3; i++) {
121*758e9fbaSOystein Eftevaag         esys_context->session_type[i] = handle_tab[i];
122*758e9fbaSOystein Eftevaag         if (handle_tab[i] == ESYS_TR_NONE || handle_tab[i] == ESYS_TR_PASSWORD) {
123*758e9fbaSOystein Eftevaag             esys_context->session_tab[i] = NULL;
124*758e9fbaSOystein Eftevaag         } else {
125*758e9fbaSOystein Eftevaag             r = esys_GetResourceObject(esys_context, handle_tab[i],
126*758e9fbaSOystein Eftevaag                                        &esys_context->session_tab[i]);
127*758e9fbaSOystein Eftevaag             return_if_error(r, "Unknown resource.");
128*758e9fbaSOystein Eftevaag 
129*758e9fbaSOystein Eftevaag             if (esys_context->session_tab[i]->rsrc.rsrcType != IESYSC_SESSION_RSRC) {
130*758e9fbaSOystein Eftevaag                 LOG_ERROR("Error: ESYS_TR is not a session resource.");
131*758e9fbaSOystein Eftevaag                 return TSS2_ESYS_RC_BAD_TR;
132*758e9fbaSOystein Eftevaag             }
133*758e9fbaSOystein Eftevaag         }
134*758e9fbaSOystein Eftevaag 
135*758e9fbaSOystein Eftevaag     }
136*758e9fbaSOystein Eftevaag     return r;
137*758e9fbaSOystein Eftevaag }
138*758e9fbaSOystein Eftevaag 
139*758e9fbaSOystein Eftevaag /** Delete all resource objects stored in the esys context.
140*758e9fbaSOystein Eftevaag  *
141*758e9fbaSOystein Eftevaag  * All resource objects stored in a linked list of the esys context are deleted.
142*758e9fbaSOystein Eftevaag  * @param[in,out] esys_context The ESYS_CONTEXT
143*758e9fbaSOystein Eftevaag  */
144*758e9fbaSOystein Eftevaag void
iesys_DeleteAllResourceObjects(ESYS_CONTEXT * esys_context)145*758e9fbaSOystein Eftevaag iesys_DeleteAllResourceObjects(ESYS_CONTEXT * esys_context)
146*758e9fbaSOystein Eftevaag {
147*758e9fbaSOystein Eftevaag     RSRC_NODE_T *node_rsrc;
148*758e9fbaSOystein Eftevaag     RSRC_NODE_T *next_node_rsrc;
149*758e9fbaSOystein Eftevaag     for (node_rsrc = esys_context->rsrc_list; node_rsrc != NULL;
150*758e9fbaSOystein Eftevaag          node_rsrc = next_node_rsrc) {
151*758e9fbaSOystein Eftevaag         next_node_rsrc = node_rsrc->next;
152*758e9fbaSOystein Eftevaag         SAFE_FREE(node_rsrc);
153*758e9fbaSOystein Eftevaag     }
154*758e9fbaSOystein Eftevaag     esys_context->rsrc_list = NULL;
155*758e9fbaSOystein Eftevaag }
156*758e9fbaSOystein Eftevaag /**  Compute the TPM nonce of the session used for parameter encryption.
157*758e9fbaSOystein Eftevaag  *
158*758e9fbaSOystein Eftevaag  * Since only encryption session can be used an error is signaled if
159*758e9fbaSOystein Eftevaag  * more encryption sessions are used.
160*758e9fbaSOystein Eftevaag  * @param[in] esys_context The ESYS_CONTEXT
161*758e9fbaSOystein Eftevaag  * @param[out] encryptNonceIndex The number of the session used for encryption.
162*758e9fbaSOystein Eftevaag  * @param[out] encryptNonce The nonce used for encryption by TPM.
163*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on Success.
164*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_MULTIPLE_ENCRYPT_SESSIONS if more than one encrypt
165*758e9fbaSOystein Eftevaag  *         session is used.
166*758e9fbaSOystein Eftevaag  */
167*758e9fbaSOystein Eftevaag TSS2_RC
iesys_compute_encrypt_nonce(ESYS_CONTEXT * esys_context,int * encryptNonceIdx,TPM2B_NONCE ** encryptNonce)168*758e9fbaSOystein Eftevaag iesys_compute_encrypt_nonce(ESYS_CONTEXT * esys_context,
169*758e9fbaSOystein Eftevaag                             int *encryptNonceIdx, TPM2B_NONCE ** encryptNonce)
170*758e9fbaSOystein Eftevaag {
171*758e9fbaSOystein Eftevaag     for (int i = 0; i < 3; i++) {
172*758e9fbaSOystein Eftevaag         RSRC_NODE_T *session = esys_context->session_tab[i];
173*758e9fbaSOystein Eftevaag         if (session != NULL) {
174*758e9fbaSOystein Eftevaag             if (session->rsrc.misc.rsrc_session.
175*758e9fbaSOystein Eftevaag                 sessionAttributes & TPMA_SESSION_ENCRYPT) {
176*758e9fbaSOystein Eftevaag                 if (*encryptNonce != NULL) {
177*758e9fbaSOystein Eftevaag                     /* Encrypt nonce already found */
178*758e9fbaSOystein Eftevaag                     return_error(TSS2_ESYS_RC_MULTIPLE_ENCRYPT_SESSIONS,
179*758e9fbaSOystein Eftevaag                                  "More than one encrypt session");
180*758e9fbaSOystein Eftevaag                 }
181*758e9fbaSOystein Eftevaag                 *encryptNonceIdx = i;
182*758e9fbaSOystein Eftevaag                 *encryptNonce = &session->rsrc.misc.rsrc_session.nonceTPM;
183*758e9fbaSOystein Eftevaag             }
184*758e9fbaSOystein Eftevaag         }
185*758e9fbaSOystein Eftevaag     }
186*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
187*758e9fbaSOystein Eftevaag }
188*758e9fbaSOystein Eftevaag 
189*758e9fbaSOystein Eftevaag /** Computation of the command parameter(cp) hashes.
190*758e9fbaSOystein Eftevaag  *
191*758e9fbaSOystein Eftevaag  * The command parameter(cp) hash of the command is computed for every
192*758e9fbaSOystein Eftevaag  * session.  If the sessions use different hash algorithms then different cp
193*758e9fbaSOystein Eftevaag  * hashes must be calculated.
194*758e9fbaSOystein Eftevaag  * The names of objects with an auth index and the command buffer are used
195*758e9fbaSOystein Eftevaag  * to compute the cp hash with the hash algorithm of the corresponding session.
196*758e9fbaSOystein Eftevaag  * The result is stored in table together with the used hash algorithm.
197*758e9fbaSOystein Eftevaag  * @param[in] esys_context The ESYS_CONTEXT
198*758e9fbaSOystein Eftevaag  * @param[in] name1 The name of the first object with an auth index.
199*758e9fbaSOystein Eftevaag  * @param[in] name2 The name of the second object with an auth index.
200*758e9fbaSOystein Eftevaag  * @param[in] name3 The name of the third object with an auth index.
201*758e9fbaSOystein Eftevaag  * @param[3] [out] cp_hash_tab An array with all cp hashes.
202*758e9fbaSOystein Eftevaag  *        The used hash algorithm is stored in this table to find the
203*758e9fbaSOystein Eftevaag  *        appropriate values for a session.
204*758e9fbaSOystein Eftevaag  * @param[out] cpHashNum Number of computed cp hash values. This value
205*758e9fbaSOystein Eftevaag  *        corresponds to the number of used hash algorithms.
206*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success,
207*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_BAD_REFERENCE for invalid parameters.
208*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_NOT_IMPLEMENTED if a hash algorithm is not implemented.
209*758e9fbaSOystein Eftevaag  * @retval TSS2_SYS_RC_* for SAPI errors.
210*758e9fbaSOystein Eftevaag  */
211*758e9fbaSOystein Eftevaag TSS2_RC
iesys_compute_cp_hashtab(ESYS_CONTEXT * esys_context,const TPM2B_NAME * name1,const TPM2B_NAME * name2,const TPM2B_NAME * name3,HASH_TAB_ITEM cp_hash_tab[3],uint8_t * cpHashNum)212*758e9fbaSOystein Eftevaag iesys_compute_cp_hashtab(ESYS_CONTEXT * esys_context,
213*758e9fbaSOystein Eftevaag                          const TPM2B_NAME * name1,
214*758e9fbaSOystein Eftevaag                          const TPM2B_NAME * name2,
215*758e9fbaSOystein Eftevaag                          const TPM2B_NAME * name3,
216*758e9fbaSOystein Eftevaag                          HASH_TAB_ITEM cp_hash_tab[3], uint8_t * cpHashNum)
217*758e9fbaSOystein Eftevaag {
218*758e9fbaSOystein Eftevaag     uint8_t ccBuffer[4];
219*758e9fbaSOystein Eftevaag     TSS2_RC r = Tss2_Sys_GetCommandCode(esys_context->sys, &ccBuffer[0]);
220*758e9fbaSOystein Eftevaag     return_if_error(r, "Error: get command code");
221*758e9fbaSOystein Eftevaag     const uint8_t *cpBuffer;
222*758e9fbaSOystein Eftevaag     size_t cpBuffer_size;
223*758e9fbaSOystein Eftevaag     r = Tss2_Sys_GetCpBuffer(esys_context->sys, &cpBuffer_size, &cpBuffer);
224*758e9fbaSOystein Eftevaag     return_if_error(r, "Error: get cp buffer");
225*758e9fbaSOystein Eftevaag     *cpHashNum = 0;
226*758e9fbaSOystein Eftevaag     for (int i = 0; i < 3; i++) {
227*758e9fbaSOystein Eftevaag         RSRC_NODE_T *session = esys_context->session_tab[i];
228*758e9fbaSOystein Eftevaag         bool cpHashFound = false;
229*758e9fbaSOystein Eftevaag         if (session != NULL) {
230*758e9fbaSOystein Eftevaag             /* We do not want to compute cpHashes multiple times for the same
231*758e9fbaSOystein Eftevaag                algorithm to save time and space */
232*758e9fbaSOystein Eftevaag             for (int j = 0; j < *cpHashNum; j++)
233*758e9fbaSOystein Eftevaag                 /* Check if cpHash for this algorithm was already computed */
234*758e9fbaSOystein Eftevaag                 if (cp_hash_tab[j].alg ==
235*758e9fbaSOystein Eftevaag                     session->rsrc.misc.rsrc_session.authHash) {
236*758e9fbaSOystein Eftevaag                     cpHashFound = true;
237*758e9fbaSOystein Eftevaag                     break;
238*758e9fbaSOystein Eftevaag                 }
239*758e9fbaSOystein Eftevaag             /* If not, we compute it and append it to the list */
240*758e9fbaSOystein Eftevaag             if (!cpHashFound) {
241*758e9fbaSOystein Eftevaag                 cp_hash_tab[*cpHashNum].size = sizeof(TPMU_HA);
242*758e9fbaSOystein Eftevaag                 r = iesys_crypto_cpHash(session->rsrc.misc.rsrc_session.
243*758e9fbaSOystein Eftevaag                                         authHash, ccBuffer, name1, name2, name3,
244*758e9fbaSOystein Eftevaag                                         cpBuffer, cpBuffer_size,
245*758e9fbaSOystein Eftevaag                                         &cp_hash_tab[*cpHashNum].digest[0],
246*758e9fbaSOystein Eftevaag                                         &cp_hash_tab[*cpHashNum].size);
247*758e9fbaSOystein Eftevaag                 return_if_error(r, "crypto cpHash");
248*758e9fbaSOystein Eftevaag 
249*758e9fbaSOystein Eftevaag                 cp_hash_tab[*cpHashNum].alg =
250*758e9fbaSOystein Eftevaag                     session->rsrc.misc.rsrc_session.authHash;
251*758e9fbaSOystein Eftevaag                 *cpHashNum += 1;
252*758e9fbaSOystein Eftevaag             }
253*758e9fbaSOystein Eftevaag         }
254*758e9fbaSOystein Eftevaag     }
255*758e9fbaSOystein Eftevaag     return r;
256*758e9fbaSOystein Eftevaag }
257*758e9fbaSOystein Eftevaag 
258*758e9fbaSOystein Eftevaag /** Computation of the response parameter (rp) hashes.
259*758e9fbaSOystein Eftevaag  * The response parameter (rp) hash of the response is computed for every
260*758e9fbaSOystein Eftevaag  * session.  If the sessions use different hash algorithms then different rp
261*758e9fbaSOystein Eftevaag  * hashes must be calculated.
262*758e9fbaSOystein Eftevaag  * The names of objects with an auth index and the command buffer are used
263*758e9fbaSOystein Eftevaag  * to compute the cp hash with the hash algorithm of the corresponding session.
264*758e9fbaSOystein Eftevaag  * The result is stored in table together with the used hash algorithm.
265*758e9fbaSOystein Eftevaag  * @param[in] esys_context The ESYS_CONTEXT
266*758e9fbaSOystein Eftevaag  * @param[in] rspAuths List of response
267*758e9fbaSOystein Eftevaag  * @param[in] const uint8_t * rpBuffer The pointer to the response buffer
268*758e9fbaSOystein Eftevaag  * @param[in] size_t rpBuffer_size The size of the response.
269*758e9fbaSOystein Eftevaag  * @param[out] HASH_TAB_ITEM rp_hash_tab[3] An array with all rp hashes.
270*758e9fbaSOystein Eftevaag  *        The used hash algorithm is stored in this table to find the
271*758e9fbaSOystein Eftevaag  *        appropriate values for a session.
272*758e9fbaSOystein Eftevaag  * @param[out] uint8_t Number of computed rp hash values. This value
273*758e9fbaSOystein Eftevaag  *        corresponds to the number of used hash algorithms.
274*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
275*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_BAD_REFERENCE for invalid parameters.
276*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_NOT_IMPLEMENTED if a hash algorithm is not implemented.
277*758e9fbaSOystein Eftevaag  * @retval TSS2_SYS_RC_* for SAPI errors.
278*758e9fbaSOystein Eftevaag  */
279*758e9fbaSOystein Eftevaag TSS2_RC
iesys_compute_rp_hashtab(ESYS_CONTEXT * esys_context,const uint8_t * rpBuffer,size_t rpBuffer_size,HASH_TAB_ITEM rp_hash_tab[3],uint8_t * rpHashNum)280*758e9fbaSOystein Eftevaag iesys_compute_rp_hashtab(ESYS_CONTEXT * esys_context,
281*758e9fbaSOystein Eftevaag                          const uint8_t * rpBuffer,
282*758e9fbaSOystein Eftevaag                          size_t rpBuffer_size,
283*758e9fbaSOystein Eftevaag                          HASH_TAB_ITEM rp_hash_tab[3], uint8_t * rpHashNum)
284*758e9fbaSOystein Eftevaag {
285*758e9fbaSOystein Eftevaag     uint8_t rcBuffer[4] = { 0 };
286*758e9fbaSOystein Eftevaag     uint8_t ccBuffer[4];
287*758e9fbaSOystein Eftevaag     TSS2_RC r = Tss2_Sys_GetCommandCode(esys_context->sys, &ccBuffer[0]);
288*758e9fbaSOystein Eftevaag     return_if_error(r, "Error: get command code");
289*758e9fbaSOystein Eftevaag 
290*758e9fbaSOystein Eftevaag     for (int i = 0; i < esys_context->authsCount; i++) {
291*758e9fbaSOystein Eftevaag         RSRC_NODE_T *session = esys_context->session_tab[i];
292*758e9fbaSOystein Eftevaag         if (session == NULL)
293*758e9fbaSOystein Eftevaag             continue;
294*758e9fbaSOystein Eftevaag         bool rpHashFound = false;
295*758e9fbaSOystein Eftevaag         /* We do not want to compute cpHashes multiple times for the same
296*758e9fbaSOystein Eftevaag            algorithm to save time and space */
297*758e9fbaSOystein Eftevaag         for (int j = 0; j < *rpHashNum; j++)
298*758e9fbaSOystein Eftevaag             if (rp_hash_tab[j].alg == session->rsrc.misc.rsrc_session.authHash) {
299*758e9fbaSOystein Eftevaag                 rpHashFound = true;
300*758e9fbaSOystein Eftevaag                 break;
301*758e9fbaSOystein Eftevaag             }
302*758e9fbaSOystein Eftevaag         /* If not, we compute it and append it to the list */
303*758e9fbaSOystein Eftevaag         if (!rpHashFound) {
304*758e9fbaSOystein Eftevaag             rp_hash_tab[*rpHashNum].size = sizeof(TPMU_HA);
305*758e9fbaSOystein Eftevaag             r = iesys_crypto_rpHash(session->rsrc.misc.rsrc_session.authHash,
306*758e9fbaSOystein Eftevaag                                     rcBuffer, ccBuffer, rpBuffer, rpBuffer_size,
307*758e9fbaSOystein Eftevaag                                     &rp_hash_tab[*rpHashNum].digest[0],
308*758e9fbaSOystein Eftevaag                                     &rp_hash_tab[*rpHashNum].size);
309*758e9fbaSOystein Eftevaag             return_if_error(r, "crypto rpHash");
310*758e9fbaSOystein Eftevaag             rp_hash_tab[*rpHashNum].alg =
311*758e9fbaSOystein Eftevaag                 session->rsrc.misc.rsrc_session.authHash;
312*758e9fbaSOystein Eftevaag             *rpHashNum += 1;
313*758e9fbaSOystein Eftevaag         }
314*758e9fbaSOystein Eftevaag     }
315*758e9fbaSOystein Eftevaag     return TPM2_RC_SUCCESS;
316*758e9fbaSOystein Eftevaag }
317*758e9fbaSOystein Eftevaag /** Create an esys resource object corresponding to a TPM object.
318*758e9fbaSOystein Eftevaag  *
319*758e9fbaSOystein Eftevaag  * The esys object is appended to the resource list stored in the esys context
320*758e9fbaSOystein Eftevaag  * (rsrc_list).
321*758e9fbaSOystein Eftevaag  * @param[in] esys_context The ESYS_CONTEXT
322*758e9fbaSOystein Eftevaag  * @param[in] esys_handle The esys handle which will be used for this object.
323*758e9fbaSOystein Eftevaag  * @param[out] esys_object The new resource object.
324*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
325*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_MEMORY if the object can not be allocated.
326*758e9fbaSOystein Eftevaag  */
327*758e9fbaSOystein Eftevaag TSS2_RC
esys_CreateResourceObject(ESYS_CONTEXT * esys_context,ESYS_TR esys_handle,RSRC_NODE_T ** esys_object)328*758e9fbaSOystein Eftevaag esys_CreateResourceObject(ESYS_CONTEXT * esys_context,
329*758e9fbaSOystein Eftevaag                           ESYS_TR esys_handle, RSRC_NODE_T ** esys_object)
330*758e9fbaSOystein Eftevaag {
331*758e9fbaSOystein Eftevaag     RSRC_NODE_T *new_esys_object = calloc(1, sizeof(RSRC_NODE_T));
332*758e9fbaSOystein Eftevaag     if (new_esys_object == NULL)
333*758e9fbaSOystein Eftevaag         return_error(TSS2_ESYS_RC_MEMORY, "Out of memory.");
334*758e9fbaSOystein Eftevaag     if (esys_context->rsrc_list == NULL) {
335*758e9fbaSOystein Eftevaag         /* The first object of the list will be added */
336*758e9fbaSOystein Eftevaag         esys_context->rsrc_list = new_esys_object;
337*758e9fbaSOystein Eftevaag         new_esys_object->next = NULL;
338*758e9fbaSOystein Eftevaag     } else {
339*758e9fbaSOystein Eftevaag         /* The new object will become the first element of the list */
340*758e9fbaSOystein Eftevaag         new_esys_object->next = esys_context->rsrc_list;
341*758e9fbaSOystein Eftevaag         esys_context->rsrc_list = new_esys_object;
342*758e9fbaSOystein Eftevaag     }
343*758e9fbaSOystein Eftevaag     *esys_object = new_esys_object;
344*758e9fbaSOystein Eftevaag     new_esys_object->esys_handle = esys_handle;
345*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
346*758e9fbaSOystein Eftevaag }
347*758e9fbaSOystein Eftevaag 
348*758e9fbaSOystein Eftevaag /** Compute tpm handle for standard esys handles.
349*758e9fbaSOystein Eftevaag  *
350*758e9fbaSOystein Eftevaag  * The tpm handle ist computed for esys handles representing pcr registers and
351*758e9fbaSOystein Eftevaag  * hierarchies.
352*758e9fbaSOystein Eftevaag  * @parm esys_handle [in] The esys handle.
353*758e9fbaSOystein Eftevaag  * @parm tpm_handle [out] The corresponding tpm handle.
354*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
355*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_BAD_VALUE if no standard handle is passed.
356*758e9fbaSOystein Eftevaag  */
357*758e9fbaSOystein Eftevaag TSS2_RC
iesys_handle_to_tpm_handle(ESYS_TR esys_handle,TPM2_HANDLE * tpm_handle)358*758e9fbaSOystein Eftevaag iesys_handle_to_tpm_handle(ESYS_TR esys_handle, TPM2_HANDLE * tpm_handle)
359*758e9fbaSOystein Eftevaag {
360*758e9fbaSOystein Eftevaag     /* Since ESYS_TR_PCR0 is equal zero only <= ESYS_TR_PCR31 has to be checked */
361*758e9fbaSOystein Eftevaag     if (esys_handle <= ESYS_TR_PCR31) {
362*758e9fbaSOystein Eftevaag         *tpm_handle = (TPM2_HANDLE) esys_handle;
363*758e9fbaSOystein Eftevaag         return TPM2_RC_SUCCESS;
364*758e9fbaSOystein Eftevaag     }
365*758e9fbaSOystein Eftevaag     if (esys_handle == ESYS_TR_RH_OWNER) {
366*758e9fbaSOystein Eftevaag         *tpm_handle = TPM2_RH_OWNER;
367*758e9fbaSOystein Eftevaag         return TPM2_RC_SUCCESS;
368*758e9fbaSOystein Eftevaag     }
369*758e9fbaSOystein Eftevaag     if (esys_handle == ESYS_TR_RH_NULL) {
370*758e9fbaSOystein Eftevaag         *tpm_handle = TPM2_RH_NULL;
371*758e9fbaSOystein Eftevaag         return TPM2_RC_SUCCESS;
372*758e9fbaSOystein Eftevaag     }
373*758e9fbaSOystein Eftevaag     if (esys_handle == ESYS_TR_RH_LOCKOUT) {
374*758e9fbaSOystein Eftevaag         *tpm_handle = TPM2_RH_LOCKOUT;
375*758e9fbaSOystein Eftevaag         return TPM2_RC_SUCCESS;
376*758e9fbaSOystein Eftevaag     }
377*758e9fbaSOystein Eftevaag     if (esys_handle == ESYS_TR_RH_ENDORSEMENT) {
378*758e9fbaSOystein Eftevaag         *tpm_handle = TPM2_RH_ENDORSEMENT;
379*758e9fbaSOystein Eftevaag         return TPM2_RC_SUCCESS;
380*758e9fbaSOystein Eftevaag     }
381*758e9fbaSOystein Eftevaag     if (esys_handle == ESYS_TR_RH_PLATFORM) {
382*758e9fbaSOystein Eftevaag         *tpm_handle = TPM2_RH_PLATFORM;
383*758e9fbaSOystein Eftevaag         return TPM2_RC_SUCCESS;
384*758e9fbaSOystein Eftevaag     }
385*758e9fbaSOystein Eftevaag     if (esys_handle == ESYS_TR_RH_PLATFORM_NV) {
386*758e9fbaSOystein Eftevaag         *tpm_handle = TPM2_RH_PLATFORM_NV;
387*758e9fbaSOystein Eftevaag         return TPM2_RC_SUCCESS;
388*758e9fbaSOystein Eftevaag     }
389*758e9fbaSOystein Eftevaag     LOG_ERROR("Error: Esys invalid ESAPI handle (%x).", esys_handle);
390*758e9fbaSOystein Eftevaag     return TSS2_ESYS_RC_BAD_VALUE;
391*758e9fbaSOystein Eftevaag }
392*758e9fbaSOystein Eftevaag /** Get the type of a tpm handle.
393*758e9fbaSOystein Eftevaag  *
394*758e9fbaSOystein Eftevaag  * @parm handle[in] The tpm handle.
395*758e9fbaSOystein Eftevaag  * @retval The part of the handle which represents the handle type.
396*758e9fbaSOystein Eftevaag  */
397*758e9fbaSOystein Eftevaag TPM2_HT
iesys_get_handle_type(TPM2_HANDLE handle)398*758e9fbaSOystein Eftevaag iesys_get_handle_type(TPM2_HANDLE handle)
399*758e9fbaSOystein Eftevaag {
400*758e9fbaSOystein Eftevaag     /* upper bytes of input data */
401*758e9fbaSOystein Eftevaag     TPM2_HT ht = (TPM2_HT) ((handle & TPM2_HR_RANGE_MASK) >> TPM2_HR_SHIFT);
402*758e9fbaSOystein Eftevaag     return ht;
403*758e9fbaSOystein Eftevaag }
404*758e9fbaSOystein Eftevaag 
405*758e9fbaSOystein Eftevaag /** Compute name derived from public info with a tpm name.
406*758e9fbaSOystein Eftevaag  *
407*758e9fbaSOystein Eftevaag  * A tpm name is computed from a public info structure and compared with a
408*758e9fbaSOystein Eftevaag  * second tpm name.
409*758e9fbaSOystein Eftevaag  * @param[in]  publicInfo The public info for name computation.
410*758e9fbaSOystein Eftevaag  * @param[in] name The name used for comparison.
411*758e9fbaSOystein Eftevaag  * @retval bool indicates whether the names are equal.
412*758e9fbaSOystein Eftevaag  */
413*758e9fbaSOystein Eftevaag bool
iesys_compare_name(TPM2B_PUBLIC * publicInfo,TPM2B_NAME * name)414*758e9fbaSOystein Eftevaag iesys_compare_name(TPM2B_PUBLIC * publicInfo, TPM2B_NAME * name)
415*758e9fbaSOystein Eftevaag {
416*758e9fbaSOystein Eftevaag     TSS2_RC r = TSS2_RC_SUCCESS;
417*758e9fbaSOystein Eftevaag     TPM2B_NAME public_info_name;
418*758e9fbaSOystein Eftevaag     if (publicInfo == NULL || name == NULL)
419*758e9fbaSOystein Eftevaag         return false;
420*758e9fbaSOystein Eftevaag     r = iesys_get_name(publicInfo, &public_info_name);
421*758e9fbaSOystein Eftevaag     if (r != TSS2_RC_SUCCESS) {
422*758e9fbaSOystein Eftevaag         LOG_DEBUG("name could not be computed.");
423*758e9fbaSOystein Eftevaag         return false;
424*758e9fbaSOystein Eftevaag     }
425*758e9fbaSOystein Eftevaag     return cmp_TPM2B_NAME(&public_info_name, name);
426*758e9fbaSOystein Eftevaag }
427*758e9fbaSOystein Eftevaag 
428*758e9fbaSOystein Eftevaag /** Compute a random salt which will be used for parameter encryption.
429*758e9fbaSOystein Eftevaag  *
430*758e9fbaSOystein Eftevaag  * Depending in the type of TPM key used for key exchange a salt will be computed.
431*758e9fbaSOystein Eftevaag  * For an ECC key an ephemeral key will be computed. This key together with the
432*758e9fbaSOystein Eftevaag  * public point of the TPMs key will be used to compute a shared secret which will
433*758e9fbaSOystein Eftevaag  * be used for the key derivation of the key for parameter encryption.
434*758e9fbaSOystein Eftevaag  * For an RSA key a random number will be computed to derive this key. The random
435*758e9fbaSOystein Eftevaag  * number will be encrypted with the TPM key.
436*758e9fbaSOystein Eftevaag  * @param[in,out]  esys_context The ESYS_CONTEXT. The generated salt will be
437*758e9fbaSOystein Eftevaag  *                 stored in this context.
438*758e9fbaSOystein Eftevaag  * @param[in] tpmKeyNode The esys resource object of the TPM key which will be
439*758e9fbaSOystein Eftevaag  *            used for key exchange.
440*758e9fbaSOystein Eftevaag  * @param[out] encryptedSalt In the case of an ECC the public point of the
441*758e9fbaSOystein Eftevaag  *             ephemeral key will be marshaled into this buffer.
442*758e9fbaSOystein Eftevaag  *             In the case of a TPM key the encrypted salt will be stored.
443*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
444*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_MEMORY Memory can not be allocated.
445*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_BAD_VALUE for invalid parameters.
446*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_BAD_REFERENCE for unexpected NULL pointer parameters.
447*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
448*758e9fbaSOystein Eftevaag  * @retval TSS2_SYS_RC_* for SAPI errors.
449*758e9fbaSOystein Eftevaag  */
450*758e9fbaSOystein Eftevaag TSS2_RC
iesys_compute_encrypted_salt(ESYS_CONTEXT * esys_context,RSRC_NODE_T * tpmKeyNode,TPM2B_ENCRYPTED_SECRET * encryptedSalt)451*758e9fbaSOystein Eftevaag iesys_compute_encrypted_salt(ESYS_CONTEXT * esys_context,
452*758e9fbaSOystein Eftevaag                              RSRC_NODE_T * tpmKeyNode,
453*758e9fbaSOystein Eftevaag                              TPM2B_ENCRYPTED_SECRET * encryptedSalt)
454*758e9fbaSOystein Eftevaag {
455*758e9fbaSOystein Eftevaag     TSS2_RC r = TSS2_RC_SUCCESS;
456*758e9fbaSOystein Eftevaag     size_t keyHash_size = 0;
457*758e9fbaSOystein Eftevaag     size_t cSize = 0;
458*758e9fbaSOystein Eftevaag     TPM2B_ECC_PARAMETER Z; /* X coordinate of privKey*publicKey */
459*758e9fbaSOystein Eftevaag     TPMS_ECC_POINT Q; /* Public point of ephemeral key */
460*758e9fbaSOystein Eftevaag 
461*758e9fbaSOystein Eftevaag     if (tpmKeyNode == 0) {
462*758e9fbaSOystein Eftevaag         encryptedSalt->size = 0;
463*758e9fbaSOystein Eftevaag         return TSS2_RC_SUCCESS;
464*758e9fbaSOystein Eftevaag     }
465*758e9fbaSOystein Eftevaag 
466*758e9fbaSOystein Eftevaag     TPM2B_PUBLIC pub = tpmKeyNode->rsrc.misc.rsrc_key_pub;
467*758e9fbaSOystein Eftevaag     if (tpmKeyNode->rsrc.rsrcType != IESYSC_KEY_RSRC) {
468*758e9fbaSOystein Eftevaag         LOG_TRACE("Public info needed.");
469*758e9fbaSOystein Eftevaag         return TSS2_ESYS_RC_BAD_VALUE;
470*758e9fbaSOystein Eftevaag     }
471*758e9fbaSOystein Eftevaag     r = iesys_crypto_hash_get_digest_size(tpmKeyNode->rsrc.misc.
472*758e9fbaSOystein Eftevaag                                           rsrc_key_pub.publicArea.nameAlg,
473*758e9fbaSOystein Eftevaag                                           &keyHash_size);
474*758e9fbaSOystein Eftevaag     return_if_error(r, "Hash algorithm not supported.");
475*758e9fbaSOystein Eftevaag 
476*758e9fbaSOystein Eftevaag     switch (pub.publicArea.type) {
477*758e9fbaSOystein Eftevaag     case TPM2_ALG_RSA:
478*758e9fbaSOystein Eftevaag 
479*758e9fbaSOystein Eftevaag         iesys_crypto_random2b((TPM2B_NONCE *) & esys_context->salt,
480*758e9fbaSOystein Eftevaag                               keyHash_size);
481*758e9fbaSOystein Eftevaag 
482*758e9fbaSOystein Eftevaag         /* When encrypting salts, the encryption scheme of a key is ignored and
483*758e9fbaSOystein Eftevaag            TPM2_ALG_OAEP is always used. */
484*758e9fbaSOystein Eftevaag         pub.publicArea.parameters.rsaDetail.scheme.scheme = TPM2_ALG_OAEP;
485*758e9fbaSOystein Eftevaag         r = iesys_crypto_pk_encrypt(&pub,
486*758e9fbaSOystein Eftevaag                                     keyHash_size, &esys_context->salt.buffer[0],
487*758e9fbaSOystein Eftevaag                                     sizeof(TPMU_ENCRYPTED_SECRET),
488*758e9fbaSOystein Eftevaag                                     (BYTE *) &encryptedSalt->secret[0], &cSize,
489*758e9fbaSOystein Eftevaag                                     "SECRET");
490*758e9fbaSOystein Eftevaag         return_if_error(r, "During encryption.");
491*758e9fbaSOystein Eftevaag         LOGBLOB_DEBUG(&encryptedSalt->secret[0], cSize, "IESYS encrypted salt");
492*758e9fbaSOystein Eftevaag         encryptedSalt->size = cSize;
493*758e9fbaSOystein Eftevaag         break;
494*758e9fbaSOystein Eftevaag     case TPM2_ALG_ECC:
495*758e9fbaSOystein Eftevaag         r = iesys_crypto_get_ecdh_point(&pub, sizeof(TPMU_ENCRYPTED_SECRET),
496*758e9fbaSOystein Eftevaag                                         &Z, &Q,
497*758e9fbaSOystein Eftevaag                                         (BYTE *) &encryptedSalt->secret[0],
498*758e9fbaSOystein Eftevaag                                         &cSize);
499*758e9fbaSOystein Eftevaag         return_if_error(r, "During computation of ECC public key.");
500*758e9fbaSOystein Eftevaag         encryptedSalt->size = cSize;
501*758e9fbaSOystein Eftevaag 
502*758e9fbaSOystein Eftevaag         /* Compute salt from Z with KDFe */
503*758e9fbaSOystein Eftevaag         r = iesys_crypto_KDFe(tpmKeyNode->rsrc.misc.
504*758e9fbaSOystein Eftevaag                               rsrc_key_pub.publicArea.nameAlg,
505*758e9fbaSOystein Eftevaag                               &Z, "SECRET", &Q.x,
506*758e9fbaSOystein Eftevaag                               &pub.publicArea.unique.ecc.x,
507*758e9fbaSOystein Eftevaag                               keyHash_size*8,
508*758e9fbaSOystein Eftevaag                               &esys_context->salt.buffer[0]);
509*758e9fbaSOystein Eftevaag         return_if_error(r, "During KDFe computation.");
510*758e9fbaSOystein Eftevaag         esys_context->salt.size = keyHash_size;
511*758e9fbaSOystein Eftevaag         break;
512*758e9fbaSOystein Eftevaag     default:
513*758e9fbaSOystein Eftevaag         LOG_ERROR("Not implemented");
514*758e9fbaSOystein Eftevaag         return TSS2_ESYS_RC_GENERAL_FAILURE;
515*758e9fbaSOystein Eftevaag         break;
516*758e9fbaSOystein Eftevaag     }
517*758e9fbaSOystein Eftevaag     return r;
518*758e9fbaSOystein Eftevaag }
519*758e9fbaSOystein Eftevaag 
520*758e9fbaSOystein Eftevaag /** Generate caller nonces for all sessions.
521*758e9fbaSOystein Eftevaag  *
522*758e9fbaSOystein Eftevaag  * For every uses session stored in context random nonce is computed.
523*758e9fbaSOystein Eftevaag  * @param[in,out]  esys_context The ESYS_CONTEXT. The generated nonces will be
524*758e9fbaSOystein Eftevaag  *                 stored in this context.
525*758e9fbaSOystein Eftevaag  * @retval TPM2_RC_SUCCESS on success. An possible error is:
526*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_BAD_VALUE if an illegal hash algorithm value is stored
527*758e9fbaSOystein Eftevaag  *         in a session.
528*758e9fbaSOystein Eftevaag  */
529*758e9fbaSOystein Eftevaag TSS2_RC
iesys_gen_caller_nonces(ESYS_CONTEXT * esys_context)530*758e9fbaSOystein Eftevaag iesys_gen_caller_nonces(ESYS_CONTEXT * esys_context)
531*758e9fbaSOystein Eftevaag {
532*758e9fbaSOystein Eftevaag     TSS2_RC r;
533*758e9fbaSOystein Eftevaag 
534*758e9fbaSOystein Eftevaag     for (int i = 0; i < 3; i++) {
535*758e9fbaSOystein Eftevaag         RSRC_NODE_T *session = esys_context->session_tab[i];
536*758e9fbaSOystein Eftevaag         if (session == NULL)
537*758e9fbaSOystein Eftevaag             continue;
538*758e9fbaSOystein Eftevaag 
539*758e9fbaSOystein Eftevaag         r = iesys_crypto_random2b(&session->rsrc.misc.rsrc_session.nonceCaller,
540*758e9fbaSOystein Eftevaag                                   session->rsrc.misc.rsrc_session.nonceCaller.size);
541*758e9fbaSOystein Eftevaag         return_if_error(r, "Error: computing caller nonce (%x).");
542*758e9fbaSOystein Eftevaag     }
543*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
544*758e9fbaSOystein Eftevaag }
545*758e9fbaSOystein Eftevaag 
546*758e9fbaSOystein Eftevaag /** Update session attributes.
547*758e9fbaSOystein Eftevaag  *
548*758e9fbaSOystein Eftevaag  * In case where command does not support param encryption/decryption
549*758e9fbaSOystein Eftevaag  * store the original session attributes and update them accordingly.
550*758e9fbaSOystein Eftevaag  * Return true is command support param encryption.
551*758e9fbaSOystein Eftevaag  *
552*758e9fbaSOystein Eftevaag  * @retval TRUE if command support param encryption
553*758e9fbaSOystein Eftevaag  * @retval FLASE if command does not support param encryption
554*758e9fbaSOystein Eftevaag  */
555*758e9fbaSOystein Eftevaag static void
iesys_update_session_flags(ESYS_CONTEXT * esys_context,IESYS_SESSION * rsrc_session)556*758e9fbaSOystein Eftevaag iesys_update_session_flags(ESYS_CONTEXT * esys_context,
557*758e9fbaSOystein Eftevaag                            IESYS_SESSION *rsrc_session)
558*758e9fbaSOystein Eftevaag {
559*758e9fbaSOystein Eftevaag     TSS2_RC r = TSS2_RC_SUCCESS;
560*758e9fbaSOystein Eftevaag     size_t param_size;
561*758e9fbaSOystein Eftevaag     const uint8_t *param_buffer;
562*758e9fbaSOystein Eftevaag 
563*758e9fbaSOystein Eftevaag     LOG_DEBUG("Checking if command supports enc/dec");
564*758e9fbaSOystein Eftevaag 
565*758e9fbaSOystein Eftevaag     rsrc_session->origSessionAttributes = rsrc_session->sessionAttributes;
566*758e9fbaSOystein Eftevaag 
567*758e9fbaSOystein Eftevaag     r = Tss2_Sys_GetDecryptParam(esys_context->sys,
568*758e9fbaSOystein Eftevaag                                  &param_size, &param_buffer);
569*758e9fbaSOystein Eftevaag     if (r == TSS2_SYS_RC_NO_DECRYPT_PARAM) {
570*758e9fbaSOystein Eftevaag         LOG_DEBUG("clear TPMA_SESSION_DECRYPT flag");
571*758e9fbaSOystein Eftevaag         rsrc_session->sessionAttributes &= ~(TPMA_SESSION_DECRYPT);
572*758e9fbaSOystein Eftevaag     }
573*758e9fbaSOystein Eftevaag 
574*758e9fbaSOystein Eftevaag     r = Tss2_Sys_GetEncryptParam(esys_context->sys,
575*758e9fbaSOystein Eftevaag                                  &param_size, &param_buffer);
576*758e9fbaSOystein Eftevaag     if (r == TSS2_SYS_RC_NO_ENCRYPT_PARAM) {
577*758e9fbaSOystein Eftevaag         LOG_DEBUG("clear TPMA_SESSION_ENCRYPT flag");
578*758e9fbaSOystein Eftevaag         rsrc_session->sessionAttributes &= ~(TPMA_SESSION_ENCRYPT);
579*758e9fbaSOystein Eftevaag     }
580*758e9fbaSOystein Eftevaag 
581*758e9fbaSOystein Eftevaag     LOG_DEBUG("Session Attrs 0x%x orig 0x%x",
582*758e9fbaSOystein Eftevaag 	      rsrc_session->sessionAttributes,
583*758e9fbaSOystein Eftevaag 	      rsrc_session->origSessionAttributes);
584*758e9fbaSOystein Eftevaag }
585*758e9fbaSOystein Eftevaag 
586*758e9fbaSOystein Eftevaag /** Restore session attributes.
587*758e9fbaSOystein Eftevaag  *
588*758e9fbaSOystein Eftevaag  * Restore original session attributes altered by iesys_update_session_flags()
589*758e9fbaSOystein Eftevaag  *
590*758e9fbaSOystein Eftevaag  * @retval void
591*758e9fbaSOystein Eftevaag  */
592*758e9fbaSOystein Eftevaag static void
iesys_restore_session_flags(ESYS_CONTEXT * esys_context)593*758e9fbaSOystein Eftevaag iesys_restore_session_flags(ESYS_CONTEXT *esys_context)
594*758e9fbaSOystein Eftevaag {
595*758e9fbaSOystein Eftevaag     LOG_DEBUG("Restoring session attribs");
596*758e9fbaSOystein Eftevaag 
597*758e9fbaSOystein Eftevaag     for (int i = 0; i < 3; i++) {
598*758e9fbaSOystein Eftevaag         RSRC_NODE_T *session = esys_context->session_tab[i];
599*758e9fbaSOystein Eftevaag         if (session == NULL)
600*758e9fbaSOystein Eftevaag             continue;
601*758e9fbaSOystein Eftevaag         IESYS_SESSION *rsrc_session = &session->rsrc.misc.rsrc_session;
602*758e9fbaSOystein Eftevaag         LOG_DEBUG("Orig Session %i Attrs 0x%x, altered Attrs x%x", i,
603*758e9fbaSOystein Eftevaag                   rsrc_session->origSessionAttributes,
604*758e9fbaSOystein Eftevaag                   rsrc_session->sessionAttributes);
605*758e9fbaSOystein Eftevaag 
606*758e9fbaSOystein Eftevaag         rsrc_session->sessionAttributes = rsrc_session->origSessionAttributes;
607*758e9fbaSOystein Eftevaag     }
608*758e9fbaSOystein Eftevaag }
609*758e9fbaSOystein Eftevaag 
610*758e9fbaSOystein Eftevaag /** Parameter encryption with AES or XOR obfuscation.
611*758e9fbaSOystein Eftevaag  *
612*758e9fbaSOystein Eftevaag  * One parameter of a TPM command will be encrypted with the selected method.
613*758e9fbaSOystein Eftevaag  * The buffer to encrypted is determined with the SAPI function:
614*758e9fbaSOystein Eftevaag  * Tss2_Sys_GetCpBuffer. If more than one encryption session es used an error
615*758e9fbaSOystein Eftevaag  * will be returned. The decryption nonce of the session used for encryption
616*758e9fbaSOystein Eftevaag  * will be returned and used for HMAC computation. The encryption key is
617*758e9fbaSOystein Eftevaag  * derived with KDFa.
618*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
619*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_MEMORY Memory can not be allocated.
620*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_BAD_VALUE for invalid parameters.
621*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_BAD_REFERENCE for unexpected NULL pointer parameters.
622*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
623*758e9fbaSOystein Eftevaag  * @retval TSS2_SYS_RC_* for SAPI errors.
624*758e9fbaSOystein Eftevaag  */
625*758e9fbaSOystein Eftevaag TSS2_RC
iesys_encrypt_param(ESYS_CONTEXT * esys_context,TPM2B_NONCE ** decryptNonce,int * decryptNonceIdx)626*758e9fbaSOystein Eftevaag iesys_encrypt_param(ESYS_CONTEXT * esys_context,
627*758e9fbaSOystein Eftevaag                     TPM2B_NONCE ** decryptNonce, int *decryptNonceIdx)
628*758e9fbaSOystein Eftevaag {
629*758e9fbaSOystein Eftevaag     TPM2B_NONCE *encryptNonce = NULL;
630*758e9fbaSOystein Eftevaag     *decryptNonceIdx = 0;
631*758e9fbaSOystein Eftevaag     *decryptNonce = NULL;
632*758e9fbaSOystein Eftevaag     TSS2_RC r = TSS2_RC_SUCCESS;
633*758e9fbaSOystein Eftevaag     esys_context->enc_session = NULL;
634*758e9fbaSOystein Eftevaag 
635*758e9fbaSOystein Eftevaag     for (int i = 0; i < 3; i++) {
636*758e9fbaSOystein Eftevaag         RSRC_NODE_T *session = esys_context->session_tab[i];
637*758e9fbaSOystein Eftevaag         if (session == NULL)
638*758e9fbaSOystein Eftevaag             continue;
639*758e9fbaSOystein Eftevaag         IESYS_SESSION *rsrc_session = &session->rsrc.misc.rsrc_session;
640*758e9fbaSOystein Eftevaag         if (rsrc_session->sessionAttributes & TPMA_SESSION_ENCRYPT)
641*758e9fbaSOystein Eftevaag             return_if_notnull(encryptNonce, "More than one encrypt session",
642*758e9fbaSOystein Eftevaag                                TSS2_ESYS_RC_MULTIPLE_ENCRYPT_SESSIONS);
643*758e9fbaSOystein Eftevaag         if (rsrc_session->sessionAttributes & TPMA_SESSION_DECRYPT)
644*758e9fbaSOystein Eftevaag             return_if_notnull(*decryptNonce, "More than one decrypt session",
645*758e9fbaSOystein Eftevaag                                TSS2_ESYS_RC_MULTIPLE_DECRYPT_SESSIONS);
646*758e9fbaSOystein Eftevaag 
647*758e9fbaSOystein Eftevaag         iesys_update_session_flags(esys_context, rsrc_session);
648*758e9fbaSOystein Eftevaag     }
649*758e9fbaSOystein Eftevaag 
650*758e9fbaSOystein Eftevaag     for (int i = 0; i < 3; i++) {
651*758e9fbaSOystein Eftevaag         RSRC_NODE_T *session = esys_context->session_tab[i];
652*758e9fbaSOystein Eftevaag         if (session == NULL)
653*758e9fbaSOystein Eftevaag             continue;
654*758e9fbaSOystein Eftevaag         IESYS_SESSION *rsrc_session = &session->rsrc.misc.rsrc_session;
655*758e9fbaSOystein Eftevaag         TPMT_SYM_DEF *symDef = &rsrc_session->symmetric;
656*758e9fbaSOystein Eftevaag 
657*758e9fbaSOystein Eftevaag         if (rsrc_session->sessionAttributes & TPMA_SESSION_ENCRYPT) {
658*758e9fbaSOystein Eftevaag             esys_context->encryptNonceIdx = i;
659*758e9fbaSOystein Eftevaag             encryptNonce = &rsrc_session->nonceTPM;
660*758e9fbaSOystein Eftevaag             esys_context->encryptNonce = encryptNonce;
661*758e9fbaSOystein Eftevaag             esys_context->enc_session = rsrc_session;
662*758e9fbaSOystein Eftevaag         }
663*758e9fbaSOystein Eftevaag 
664*758e9fbaSOystein Eftevaag         /* Session for encryption found */
665*758e9fbaSOystein Eftevaag         if (rsrc_session->sessionAttributes & TPMA_SESSION_DECRYPT) {
666*758e9fbaSOystein Eftevaag             *decryptNonceIdx = i;
667*758e9fbaSOystein Eftevaag             *decryptNonce = &rsrc_session->nonceTPM;
668*758e9fbaSOystein Eftevaag             size_t hlen;
669*758e9fbaSOystein Eftevaag             r = iesys_crypto_hash_get_digest_size(rsrc_session->authHash, &hlen);
670*758e9fbaSOystein Eftevaag             return_if_error(r, "get digest size");
671*758e9fbaSOystein Eftevaag             size_t key_len = TPM2_MAX_SYM_KEY_BYTES + TPM2_MAX_SYM_BLOCK_SIZE;
672*758e9fbaSOystein Eftevaag             if (key_len % hlen > 0)
673*758e9fbaSOystein Eftevaag                 key_len = key_len + hlen - (key_len % hlen);
674*758e9fbaSOystein Eftevaag             uint8_t symKey[key_len];
675*758e9fbaSOystein Eftevaag             size_t paramSize = 0;
676*758e9fbaSOystein Eftevaag             const uint8_t *paramBuffer;
677*758e9fbaSOystein Eftevaag 
678*758e9fbaSOystein Eftevaag             r = Tss2_Sys_GetDecryptParam(esys_context->sys, &paramSize,
679*758e9fbaSOystein Eftevaag                                          &paramBuffer);
680*758e9fbaSOystein Eftevaag             return_if_error(r, "Encryption not possible");
681*758e9fbaSOystein Eftevaag 
682*758e9fbaSOystein Eftevaag             if (paramSize == 0)
683*758e9fbaSOystein Eftevaag                 continue;
684*758e9fbaSOystein Eftevaag 
685*758e9fbaSOystein Eftevaag             BYTE encrypt_buffer[paramSize];
686*758e9fbaSOystein Eftevaag             memcpy(&encrypt_buffer[0], paramBuffer, paramSize);
687*758e9fbaSOystein Eftevaag             LOGBLOB_DEBUG(paramBuffer, paramSize, "param to encrypt");
688*758e9fbaSOystein Eftevaag 
689*758e9fbaSOystein Eftevaag             /* AES encryption with key derived with KDFa */
690*758e9fbaSOystein Eftevaag             if (symDef->algorithm == TPM2_ALG_AES) {
691*758e9fbaSOystein Eftevaag                 if (symDef->mode.aes != TPM2_ALG_CFB) {
692*758e9fbaSOystein Eftevaag                     return_error(TSS2_ESYS_RC_BAD_VALUE,
693*758e9fbaSOystein Eftevaag                                  "Invalid symmetric mode (must be CFB)");
694*758e9fbaSOystein Eftevaag                 }
695*758e9fbaSOystein Eftevaag                 r = iesys_crypto_KDFa(rsrc_session->authHash,
696*758e9fbaSOystein Eftevaag                                       &rsrc_session->sessionValue[0],
697*758e9fbaSOystein Eftevaag                                       rsrc_session->sizeSessionValue, "CFB",
698*758e9fbaSOystein Eftevaag                                       &rsrc_session->nonceCaller,
699*758e9fbaSOystein Eftevaag                                       &rsrc_session->nonceTPM,
700*758e9fbaSOystein Eftevaag                                       symDef->keyBits.aes + AES_BLOCK_SIZE_IN_BYTES * 8,
701*758e9fbaSOystein Eftevaag                                       NULL, &symKey[0], FALSE);
702*758e9fbaSOystein Eftevaag                 return_if_error(r, "while computing KDFa");
703*758e9fbaSOystein Eftevaag 
704*758e9fbaSOystein Eftevaag                 size_t aes_off = ( symDef->keyBits.aes + 7) / 8;
705*758e9fbaSOystein Eftevaag                 r = iesys_crypto_sym_aes_encrypt(&symKey[0],
706*758e9fbaSOystein Eftevaag                                                  symDef->algorithm,
707*758e9fbaSOystein Eftevaag                                                  symDef->keyBits.aes,
708*758e9fbaSOystein Eftevaag                                                  symDef->mode.aes,
709*758e9fbaSOystein Eftevaag                                                  AES_BLOCK_SIZE_IN_BYTES,
710*758e9fbaSOystein Eftevaag                                                  &encrypt_buffer[0], paramSize,
711*758e9fbaSOystein Eftevaag                                                  &symKey[aes_off]);
712*758e9fbaSOystein Eftevaag                 return_if_error(r, "AES encryption not possible");
713*758e9fbaSOystein Eftevaag             }
714*758e9fbaSOystein Eftevaag             /* XOR obfuscation of parameter */
715*758e9fbaSOystein Eftevaag             else if (symDef->algorithm == TPM2_ALG_XOR) {
716*758e9fbaSOystein Eftevaag                 r = iesys_xor_parameter_obfuscation(rsrc_session->authHash,
717*758e9fbaSOystein Eftevaag                                                     &rsrc_session->sessionValue[0],
718*758e9fbaSOystein Eftevaag                                                     rsrc_session->sizeSessionValue,
719*758e9fbaSOystein Eftevaag                                                     &rsrc_session->nonceCaller,
720*758e9fbaSOystein Eftevaag                                                     &rsrc_session->nonceTPM,
721*758e9fbaSOystein Eftevaag                                                     &encrypt_buffer[0],
722*758e9fbaSOystein Eftevaag                                                     paramSize);
723*758e9fbaSOystein Eftevaag                 return_if_error(r, "XOR obfuscation not possible.");
724*758e9fbaSOystein Eftevaag 
725*758e9fbaSOystein Eftevaag             } else {
726*758e9fbaSOystein Eftevaag                 return_error(TSS2_ESYS_RC_BAD_VALUE,
727*758e9fbaSOystein Eftevaag                              "Invalid symmetric algorithm (should be XOR or AES)");
728*758e9fbaSOystein Eftevaag             }
729*758e9fbaSOystein Eftevaag             r = Tss2_Sys_SetDecryptParam(esys_context->sys, paramSize,
730*758e9fbaSOystein Eftevaag                                          &encrypt_buffer[0]);
731*758e9fbaSOystein Eftevaag             return_if_error(r, "Set encrypt parameter not possible");
732*758e9fbaSOystein Eftevaag 
733*758e9fbaSOystein Eftevaag         }
734*758e9fbaSOystein Eftevaag     }
735*758e9fbaSOystein Eftevaag     return r;
736*758e9fbaSOystein Eftevaag }
737*758e9fbaSOystein Eftevaag 
738*758e9fbaSOystein Eftevaag /** Parameter decryption with AES or XOR obfuscation.
739*758e9fbaSOystein Eftevaag  *
740*758e9fbaSOystein Eftevaag  * One parameter of a TPM response will be decrypted with the selected method.
741*758e9fbaSOystein Eftevaag  * @param[in]  esys_context The ESYS_CONTEXT.
742*758e9fbaSOystein Eftevaag  *
743*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
744*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_MEMORY Memory can not be allocated.
745*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_BAD_VALUE for invalid parameters.
746*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_BAD_REFERENCE for unexpected NULL pointer parameters.
747*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
748*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_NOT_IMPLEMENTED if hash algorithm is not implemented.
749*758e9fbaSOystein Eftevaag  * @retval TSS2_SYS_RC_* for SAPI errors.
750*758e9fbaSOystein Eftevaag  */
751*758e9fbaSOystein Eftevaag TSS2_RC
iesys_decrypt_param(ESYS_CONTEXT * esys_context)752*758e9fbaSOystein Eftevaag iesys_decrypt_param(ESYS_CONTEXT * esys_context)
753*758e9fbaSOystein Eftevaag {
754*758e9fbaSOystein Eftevaag     TSS2_RC r;
755*758e9fbaSOystein Eftevaag     const uint8_t *ciphertext;
756*758e9fbaSOystein Eftevaag     size_t p2BSize;
757*758e9fbaSOystein Eftevaag     size_t hlen;
758*758e9fbaSOystein Eftevaag     RSRC_NODE_T *session;
759*758e9fbaSOystein Eftevaag     IESYS_SESSION *rsrc_session;
760*758e9fbaSOystein Eftevaag     TPMT_SYM_DEF *symDef;
761*758e9fbaSOystein Eftevaag     size_t key_len = TPM2_MAX_SYM_KEY_BYTES + TPM2_MAX_SYM_BLOCK_SIZE;
762*758e9fbaSOystein Eftevaag 
763*758e9fbaSOystein Eftevaag     session = esys_context->session_tab[esys_context->encryptNonceIdx];
764*758e9fbaSOystein Eftevaag     rsrc_session = &session->rsrc.misc.rsrc_session;
765*758e9fbaSOystein Eftevaag     symDef = &rsrc_session->symmetric;
766*758e9fbaSOystein Eftevaag 
767*758e9fbaSOystein Eftevaag     r = iesys_crypto_hash_get_digest_size(rsrc_session->authHash, &hlen);
768*758e9fbaSOystein Eftevaag     return_if_error(r, "Error");
769*758e9fbaSOystein Eftevaag     if (key_len % hlen > 0)
770*758e9fbaSOystein Eftevaag         key_len = key_len + hlen - (key_len % hlen);
771*758e9fbaSOystein Eftevaag 
772*758e9fbaSOystein Eftevaag     uint8_t symKey[key_len];
773*758e9fbaSOystein Eftevaag 
774*758e9fbaSOystein Eftevaag     r = Tss2_Sys_GetEncryptParam(esys_context->sys, &p2BSize, &ciphertext);
775*758e9fbaSOystein Eftevaag     return_if_error(r, "Getting encrypt param");
776*758e9fbaSOystein Eftevaag 
777*758e9fbaSOystein Eftevaag     UINT8 plaintext[p2BSize];
778*758e9fbaSOystein Eftevaag     memcpy(&plaintext[0], ciphertext, p2BSize);
779*758e9fbaSOystein Eftevaag 
780*758e9fbaSOystein Eftevaag     if (symDef->algorithm == TPM2_ALG_AES) {
781*758e9fbaSOystein Eftevaag         /* Parameter decryption with a symmetric AES key derived by KDFa */
782*758e9fbaSOystein Eftevaag         if (symDef->mode.aes != TPM2_ALG_CFB) {
783*758e9fbaSOystein Eftevaag             return_error(TSS2_ESYS_RC_BAD_VALUE,
784*758e9fbaSOystein Eftevaag                          "Invalid symmetric mode (must be CFB)");
785*758e9fbaSOystein Eftevaag         }
786*758e9fbaSOystein Eftevaag         LOGBLOB_DEBUG(&rsrc_session->sessionKey.buffer[0],
787*758e9fbaSOystein Eftevaag                       rsrc_session->sessionKey.size,
788*758e9fbaSOystein Eftevaag                       "IESYS encrypt session key");
789*758e9fbaSOystein Eftevaag 
790*758e9fbaSOystein Eftevaag         r = iesys_crypto_KDFa(rsrc_session->authHash,
791*758e9fbaSOystein Eftevaag                               &rsrc_session->sessionValue[0],
792*758e9fbaSOystein Eftevaag                               rsrc_session->sizeSessionValue,
793*758e9fbaSOystein Eftevaag                               "CFB", &rsrc_session->nonceTPM,
794*758e9fbaSOystein Eftevaag                               &rsrc_session->nonceCaller,
795*758e9fbaSOystein Eftevaag                               symDef->keyBits.aes
796*758e9fbaSOystein Eftevaag                               + AES_BLOCK_SIZE_IN_BYTES * 8, NULL,
797*758e9fbaSOystein Eftevaag                               &symKey[0], FALSE);
798*758e9fbaSOystein Eftevaag         return_if_error(r, "KDFa error");
799*758e9fbaSOystein Eftevaag         LOGBLOB_DEBUG(&symKey[0],
800*758e9fbaSOystein Eftevaag                       ((symDef->keyBits.aes +
801*758e9fbaSOystein Eftevaag                         AES_BLOCK_SIZE_IN_BYTES * 8) + 7) / 8,
802*758e9fbaSOystein Eftevaag                       "IESYS encrypt KDFa key");
803*758e9fbaSOystein Eftevaag 
804*758e9fbaSOystein Eftevaag         size_t aes_off = ( symDef->keyBits.aes + 7) / 8;
805*758e9fbaSOystein Eftevaag         r = iesys_crypto_sym_aes_decrypt(&symKey[0],
806*758e9fbaSOystein Eftevaag                                      symDef->algorithm,
807*758e9fbaSOystein Eftevaag                                      symDef->keyBits.aes,
808*758e9fbaSOystein Eftevaag                                      symDef->mode.aes,
809*758e9fbaSOystein Eftevaag                                      AES_BLOCK_SIZE_IN_BYTES,
810*758e9fbaSOystein Eftevaag                                      &plaintext[0], p2BSize,
811*758e9fbaSOystein Eftevaag                                      &symKey[aes_off]);
812*758e9fbaSOystein Eftevaag         return_if_error(r, "Decryption error");
813*758e9fbaSOystein Eftevaag 
814*758e9fbaSOystein Eftevaag         r = Tss2_Sys_SetEncryptParam(esys_context->sys, p2BSize, &plaintext[0]);
815*758e9fbaSOystein Eftevaag         return_if_error(r, "Setting plaintext");
816*758e9fbaSOystein Eftevaag     } else if (symDef->algorithm == TPM2_ALG_XOR) {
817*758e9fbaSOystein Eftevaag         /* Parameter decryption with XOR obfuscation */
818*758e9fbaSOystein Eftevaag         r = iesys_xor_parameter_obfuscation(rsrc_session->authHash,
819*758e9fbaSOystein Eftevaag                                             &rsrc_session->sessionValue[0],
820*758e9fbaSOystein Eftevaag                                             rsrc_session->sizeSessionValue,
821*758e9fbaSOystein Eftevaag                                             &rsrc_session->nonceTPM,
822*758e9fbaSOystein Eftevaag                                             &rsrc_session->nonceCaller,
823*758e9fbaSOystein Eftevaag                                             &plaintext[0],
824*758e9fbaSOystein Eftevaag                                             p2BSize);
825*758e9fbaSOystein Eftevaag         return_if_error(r, "XOR obfuscation not possible.");
826*758e9fbaSOystein Eftevaag 
827*758e9fbaSOystein Eftevaag         r = Tss2_Sys_SetEncryptParam(esys_context->sys, p2BSize, &plaintext[0]);
828*758e9fbaSOystein Eftevaag         return_if_error(r, "Setting plaintext");
829*758e9fbaSOystein Eftevaag     } else {
830*758e9fbaSOystein Eftevaag         return_error(TSS2_ESYS_RC_BAD_VALUE,
831*758e9fbaSOystein Eftevaag                      "Invalid symmetric algorithm (should be XOR or AES)");
832*758e9fbaSOystein Eftevaag     }
833*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
834*758e9fbaSOystein Eftevaag }
835*758e9fbaSOystein Eftevaag 
836*758e9fbaSOystein Eftevaag /** Check the HMAC values of the response for all sessions.
837*758e9fbaSOystein Eftevaag  *
838*758e9fbaSOystein Eftevaag  * The HMAC values are computed based on the session secrets, the used nonces,
839*758e9fbaSOystein Eftevaag  * the session attributes, the response hash.
840*758e9fbaSOystein Eftevaag  * @param[in] esys_context The ESYS_CONTEXT.
841*758e9fbaSOystein Eftevaag  * @param[in] rspAuths The list of the session auth values.
842*758e9fbaSOystein Eftevaag  * @param[in] rp_hashtab  The list of response hashes.
843*758e9fbaSOystein Eftevaag  * @param[in] rpHashNum The number of response hashes.
844*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
845*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_MEMORY Memory can not be allocated.
846*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_BAD_VALUE for invalid parameters.
847*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
848*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_NOT_IMPLEMENTED if hash algorithm is not implemented.
849*758e9fbaSOystein Eftevaag  */
850*758e9fbaSOystein Eftevaag TSS2_RC
iesys_check_rp_hmacs(ESYS_CONTEXT * esys_context,TSS2L_SYS_AUTH_RESPONSE * rspAuths,HASH_TAB_ITEM rp_hash_tab[3],uint8_t rpHashNum)851*758e9fbaSOystein Eftevaag iesys_check_rp_hmacs(ESYS_CONTEXT * esys_context,
852*758e9fbaSOystein Eftevaag                      TSS2L_SYS_AUTH_RESPONSE * rspAuths,
853*758e9fbaSOystein Eftevaag                      HASH_TAB_ITEM rp_hash_tab[3],
854*758e9fbaSOystein Eftevaag                      uint8_t rpHashNum)
855*758e9fbaSOystein Eftevaag {
856*758e9fbaSOystein Eftevaag     TSS2_RC r;
857*758e9fbaSOystein Eftevaag 
858*758e9fbaSOystein Eftevaag     for (int i = 0; i < rspAuths->count; i++) {
859*758e9fbaSOystein Eftevaag         RSRC_NODE_T *session = esys_context->session_tab[i];
860*758e9fbaSOystein Eftevaag         if (session == NULL)
861*758e9fbaSOystein Eftevaag             continue;
862*758e9fbaSOystein Eftevaag 
863*758e9fbaSOystein Eftevaag         IESYS_SESSION *rsrc_session = &session->rsrc.misc.rsrc_session;
864*758e9fbaSOystein Eftevaag         if (rsrc_session->type_policy_session == POLICY_PASSWORD) {
865*758e9fbaSOystein Eftevaag             /* A policy password session has no auth value */
866*758e9fbaSOystein Eftevaag             if (rspAuths->auths[i].hmac.size != 0) {
867*758e9fbaSOystein Eftevaag                 LOG_ERROR("PolicyPassword session's HMAC must be 0-length.");
868*758e9fbaSOystein Eftevaag                 return TSS2_ESYS_RC_RSP_AUTH_FAILED;
869*758e9fbaSOystein Eftevaag             }
870*758e9fbaSOystein Eftevaag             continue;
871*758e9fbaSOystein Eftevaag         }
872*758e9fbaSOystein Eftevaag 
873*758e9fbaSOystein Eftevaag         /* Find the rpHash for the hash algorithm used by this session */
874*758e9fbaSOystein Eftevaag         int hi;
875*758e9fbaSOystein Eftevaag         for (hi = 0; hi < rpHashNum; hi++) {
876*758e9fbaSOystein Eftevaag             if (rsrc_session->authHash == rp_hash_tab[hi].alg) {
877*758e9fbaSOystein Eftevaag                 break;
878*758e9fbaSOystein Eftevaag             }
879*758e9fbaSOystein Eftevaag         }
880*758e9fbaSOystein Eftevaag         if (hi == rpHashNum) {
881*758e9fbaSOystein Eftevaag             LOG_ERROR("rpHash for alg %"PRIx16 " not found.",
882*758e9fbaSOystein Eftevaag                       rsrc_session->authHash);
883*758e9fbaSOystein Eftevaag             return TSS2_ESYS_RC_GENERAL_FAILURE;
884*758e9fbaSOystein Eftevaag         }
885*758e9fbaSOystein Eftevaag 
886*758e9fbaSOystein Eftevaag         TPM2B_AUTH rp_hmac;
887*758e9fbaSOystein Eftevaag         rp_hmac.size = sizeof(TPMU_HA);
888*758e9fbaSOystein Eftevaag         rsrc_session->nonceTPM = rspAuths->auths[i].nonce;
889*758e9fbaSOystein Eftevaag         rsrc_session->sessionAttributes =
890*758e9fbaSOystein Eftevaag             rspAuths->auths[i].sessionAttributes;
891*758e9fbaSOystein Eftevaag         r = iesys_crypto_authHmac(rsrc_session->authHash,
892*758e9fbaSOystein Eftevaag                                   &rsrc_session->sessionValue[0],
893*758e9fbaSOystein Eftevaag                                   rsrc_session->sizeHmacValue,
894*758e9fbaSOystein Eftevaag                                   &rp_hash_tab[hi].digest[0],
895*758e9fbaSOystein Eftevaag                                   rp_hash_tab[hi].size,
896*758e9fbaSOystein Eftevaag                                   &rsrc_session->nonceTPM,
897*758e9fbaSOystein Eftevaag                                   &rsrc_session->nonceCaller, NULL, NULL,
898*758e9fbaSOystein Eftevaag                                   rspAuths->auths[i].sessionAttributes,
899*758e9fbaSOystein Eftevaag                                   &rp_hmac);
900*758e9fbaSOystein Eftevaag         return_if_error(r, "HMAC error");
901*758e9fbaSOystein Eftevaag 
902*758e9fbaSOystein Eftevaag         if (!cmp_TPM2B_AUTH(&rspAuths->auths[i].hmac, &rp_hmac)) {
903*758e9fbaSOystein Eftevaag             LOG_ERROR("TPM's response auth is invalid for session %i", i);
904*758e9fbaSOystein Eftevaag             return TSS2_ESYS_RC_RSP_AUTH_FAILED;
905*758e9fbaSOystein Eftevaag         }
906*758e9fbaSOystein Eftevaag     }
907*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
908*758e9fbaSOystein Eftevaag }
909*758e9fbaSOystein Eftevaag /** Compute the value for check of bind authorization.
910*758e9fbaSOystein Eftevaag  *
911*758e9fbaSOystein Eftevaag  * This value has to be computed from the bind object in the StartAuthSession
912*758e9fbaSOystein Eftevaag  * command and later checked in for corresponding object authorizations.
913*758e9fbaSOystein Eftevaag  * @param[in] name The name of the bind object.
914*758e9fbaSOystein Eftevaag  * @param[in] auth The authorization of the bind object.
915*758e9fbaSOystein Eftevaag  * @param[out] bound_entity The value used for checking the bind authorization.
916*758e9fbaSOystein Eftevaag  */
917*758e9fbaSOystein Eftevaag void
iesys_compute_bound_entity(const TPM2B_NAME * name,const TPM2B_AUTH * auth,TPM2B_NAME * bound_entity)918*758e9fbaSOystein Eftevaag iesys_compute_bound_entity(const TPM2B_NAME * name,
919*758e9fbaSOystein Eftevaag                            const TPM2B_AUTH * auth, TPM2B_NAME * bound_entity)
920*758e9fbaSOystein Eftevaag {
921*758e9fbaSOystein Eftevaag     UINT16 i;
922*758e9fbaSOystein Eftevaag     UINT16 j = 0;
923*758e9fbaSOystein Eftevaag     *bound_entity = *name;
924*758e9fbaSOystein Eftevaag     memset(&bound_entity->name[bound_entity->size], 0,
925*758e9fbaSOystein Eftevaag            sizeof(bound_entity->name) - bound_entity->size);
926*758e9fbaSOystein Eftevaag     for (i = sizeof(bound_entity->name) - auth->size;
927*758e9fbaSOystein Eftevaag          i < sizeof(bound_entity->name); i++)
928*758e9fbaSOystein Eftevaag         bound_entity->name[i] ^= auth->buffer[j++];
929*758e9fbaSOystein Eftevaag     bound_entity->size = sizeof(bound_entity->name);
930*758e9fbaSOystein Eftevaag }
931*758e9fbaSOystein Eftevaag 
932*758e9fbaSOystein Eftevaag /** Predicate whether the authorization is for the object bound to the session.
933*758e9fbaSOystein Eftevaag  *
934*758e9fbaSOystein Eftevaag  * @param[in] name The name of the object.
935*758e9fbaSOystein Eftevaag  * @param[in] auth The auth value of the object.
936*758e9fbaSOystein Eftevaag  * @param[in] sesssion The session to be checked.
937*758e9fbaSOystein Eftevaag  * @retval true if object is bind object of session.
938*758e9fbaSOystein Eftevaag  * @retval false if not.
939*758e9fbaSOystein Eftevaag  */
940*758e9fbaSOystein Eftevaag bool
iesys_is_object_bound(const TPM2B_NAME * name,const TPM2B_AUTH * auth,RSRC_NODE_T * session)941*758e9fbaSOystein Eftevaag iesys_is_object_bound(const TPM2B_NAME * name,
942*758e9fbaSOystein Eftevaag                       const TPM2B_AUTH * auth, RSRC_NODE_T * session)
943*758e9fbaSOystein Eftevaag {
944*758e9fbaSOystein Eftevaag     TPM2B_NAME tmp;
945*758e9fbaSOystein Eftevaag     if (session->rsrc.misc.rsrc_session.bound_entity.size == 0)
946*758e9fbaSOystein Eftevaag         /* No bind session */
947*758e9fbaSOystein Eftevaag         return false;
948*758e9fbaSOystein Eftevaag     iesys_compute_bound_entity(name, auth, &tmp);
949*758e9fbaSOystein Eftevaag     return cmp_TPM2B_NAME(&session->rsrc.misc.rsrc_session.bound_entity, &tmp);
950*758e9fbaSOystein Eftevaag }
951*758e9fbaSOystein Eftevaag 
952*758e9fbaSOystein Eftevaag /**
953*758e9fbaSOystein Eftevaag  * Compute the session value
954*758e9fbaSOystein Eftevaag  *
955*758e9fbaSOystein Eftevaag  * This function derives the session value from the session key
956*758e9fbaSOystein Eftevaag  * and the auth value. The auth value is appended to the session key.
957*758e9fbaSOystein Eftevaag  * The session value is used for key derivation for parameter encryption and
958*758e9fbaSOystein Eftevaag  * HMAC computation. There is one exception for HMAC key derivation: If the
959*758e9fbaSOystein Eftevaag  * session is bound to an object only the session key is used. The auth value
960*758e9fbaSOystein Eftevaag  * is appended only for the key used for parameter encryption.
961*758e9fbaSOystein Eftevaag  * The auth value is only used if an authorization is necessary and the name
962*758e9fbaSOystein Eftevaag  * of the object is not equal to the name of an used bound entity
963*758e9fbaSOystein Eftevaag  * @param[in,out] session for which the session value will be computed.
964*758e9fbaSOystein Eftevaag  *       The value will be stored in sessionValue of the session object.
965*758e9fbaSOystein Eftevaag  *       The length of the object will be stored in sizeHmacValue and
966*758e9fbaSOystein Eftevaag  *       sizeSessionValue respectively to the purpose of usage (HMAC computation
967*758e9fbaSOystein Eftevaag  *       or parameter encryption).
968*758e9fbaSOystein Eftevaag  * @param[in] name name of the object to be authorized (NULL if no authorization)
969*758e9fbaSOystein Eftevaag  * @param[in] auth_value auth value of the object to be authorized
970*758e9fbaSOystein Eftevaag  *             (NULL if no authorization)
971*758e9fbaSOystein Eftevaag  */
972*758e9fbaSOystein Eftevaag void
iesys_compute_session_value(RSRC_NODE_T * session,const TPM2B_NAME * name,const TPM2B_AUTH * auth_value)973*758e9fbaSOystein Eftevaag iesys_compute_session_value(RSRC_NODE_T * session,
974*758e9fbaSOystein Eftevaag                             const TPM2B_NAME * name,
975*758e9fbaSOystein Eftevaag                             const TPM2B_AUTH * auth_value)
976*758e9fbaSOystein Eftevaag {
977*758e9fbaSOystein Eftevaag     if (session == NULL)
978*758e9fbaSOystein Eftevaag         return;
979*758e9fbaSOystein Eftevaag 
980*758e9fbaSOystein Eftevaag     /* First the session Key is copied into the sessionValue */
981*758e9fbaSOystein Eftevaag     session->rsrc.misc.rsrc_session.sizeSessionValue
982*758e9fbaSOystein Eftevaag         = session->rsrc.misc.rsrc_session.sessionKey.size;
983*758e9fbaSOystein Eftevaag     memcpy(&session->rsrc.misc.rsrc_session.sessionValue[0],
984*758e9fbaSOystein Eftevaag            &session->rsrc.misc.rsrc_session.sessionKey.buffer[0],
985*758e9fbaSOystein Eftevaag            session->rsrc.misc.rsrc_session.sessionKey.size);
986*758e9fbaSOystein Eftevaag 
987*758e9fbaSOystein Eftevaag      /* This requires an HMAC Session and not a password session */
988*758e9fbaSOystein Eftevaag     if (session->rsrc.misc.rsrc_session.sessionType != TPM2_SE_HMAC &&
989*758e9fbaSOystein Eftevaag         session->rsrc.misc.rsrc_session.sessionType != TPM2_SE_POLICY)
990*758e9fbaSOystein Eftevaag         return;
991*758e9fbaSOystein Eftevaag 
992*758e9fbaSOystein Eftevaag     session->rsrc.misc.rsrc_session.sizeHmacValue = session->rsrc.misc.rsrc_session.sizeSessionValue;
993*758e9fbaSOystein Eftevaag 
994*758e9fbaSOystein Eftevaag     if (name == NULL || auth_value == NULL)
995*758e9fbaSOystein Eftevaag         return;
996*758e9fbaSOystein Eftevaag 
997*758e9fbaSOystein Eftevaag     /* The auth value is appended to the session key */
998*758e9fbaSOystein Eftevaag     memcpy(&session->rsrc.misc.rsrc_session.
999*758e9fbaSOystein Eftevaag            sessionValue[session->rsrc.misc.rsrc_session.sessionKey.size],
1000*758e9fbaSOystein Eftevaag            &auth_value->buffer[0], auth_value->size);
1001*758e9fbaSOystein Eftevaag     session->rsrc.misc.rsrc_session.sizeSessionValue += auth_value->size;
1002*758e9fbaSOystein Eftevaag 
1003*758e9fbaSOystein Eftevaag     /* Then if we are a bound session, the auth value is not appended to the end
1004*758e9fbaSOystein Eftevaag        of the session value for HMAC computation. The size of the key will not be
1005*758e9fbaSOystein Eftevaag        increased.*/
1006*758e9fbaSOystein Eftevaag     if (iesys_is_object_bound(name, auth_value, session))
1007*758e9fbaSOystein Eftevaag         return;
1008*758e9fbaSOystein Eftevaag 
1009*758e9fbaSOystein Eftevaag     /* type_policy_session set to POLICY_AUTH by command PolicyAuthValue */
1010*758e9fbaSOystein Eftevaag     if (session->rsrc.misc.rsrc_session.sessionType == TPM2_SE_POLICY &&
1011*758e9fbaSOystein Eftevaag         session->rsrc.misc.rsrc_session.type_policy_session != POLICY_AUTH)
1012*758e9fbaSOystein Eftevaag         return;
1013*758e9fbaSOystein Eftevaag 
1014*758e9fbaSOystein Eftevaag     session->rsrc.misc.rsrc_session.sizeHmacValue += auth_value->size;
1015*758e9fbaSOystein Eftevaag }
1016*758e9fbaSOystein Eftevaag 
1017*758e9fbaSOystein Eftevaag /**
1018*758e9fbaSOystein Eftevaag  * Lookup the object to a handle from inside the context.
1019*758e9fbaSOystein Eftevaag  *
1020*758e9fbaSOystein Eftevaag  * This function searches the esapi context for an object that corresponds to a
1021*758e9fbaSOystein Eftevaag  * provided esys_handle. These objects contain information such as the
1022*758e9fbaSOystein Eftevaag  * appropriate tpm handle, the public name or the stored auth values.
1023*758e9fbaSOystein Eftevaag  * These esys handles refer either to an object previously initialized on the
1024*758e9fbaSOystein Eftevaag  * same context, in which case this will be returned. Or they refer to a
1025*758e9fbaSOystein Eftevaag  * "global", in which case the corresponding object will be created if it does
1026*758e9fbaSOystein Eftevaag  * not exist yet.
1027*758e9fbaSOystein Eftevaag  * @param[in,out] esys_context The esys context to issue the command on.
1028*758e9fbaSOystein Eftevaag  * @param[in] esys_handle The handle to find the corresponding object for.
1029*758e9fbaSOystein Eftevaag  * @param[out] esys_object The object containing the name, tpm handle and auth value
1030*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
1031*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_BAD_TR if the handle is invalid.
1032*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_BAD_VALUE if an unknown handle < ESYS_TR_MIN_OBJECT is
1033*758e9fbaSOystein Eftevaag  *         passed.
1034*758e9fbaSOystein Eftevaag  */
1035*758e9fbaSOystein Eftevaag TSS2_RC
esys_GetResourceObject(ESYS_CONTEXT * esys_context,ESYS_TR esys_handle,RSRC_NODE_T ** esys_object)1036*758e9fbaSOystein Eftevaag esys_GetResourceObject(ESYS_CONTEXT * esys_context,
1037*758e9fbaSOystein Eftevaag                        ESYS_TR esys_handle, RSRC_NODE_T ** esys_object)
1038*758e9fbaSOystein Eftevaag {
1039*758e9fbaSOystein Eftevaag     RSRC_NODE_T *esys_object_aux;
1040*758e9fbaSOystein Eftevaag     TPM2_HANDLE tpm_handle;
1041*758e9fbaSOystein Eftevaag     size_t offset = 0;
1042*758e9fbaSOystein Eftevaag     TSS2_RC r;
1043*758e9fbaSOystein Eftevaag 
1044*758e9fbaSOystein Eftevaag     /* Sometimes the TPM API allows for optional objects. In those cases we map
1045*758e9fbaSOystein Eftevaag        the object node to NULL. This will be handled accordingly by following
1046*758e9fbaSOystein Eftevaag        code */
1047*758e9fbaSOystein Eftevaag     if (esys_handle == ESYS_TR_NONE) {
1048*758e9fbaSOystein Eftevaag         *esys_object = NULL;
1049*758e9fbaSOystein Eftevaag         return TSS2_RC_SUCCESS;
1050*758e9fbaSOystein Eftevaag     }
1051*758e9fbaSOystein Eftevaag 
1052*758e9fbaSOystein Eftevaag     /* The typical case is that we have a resource object already within the
1053*758e9fbaSOystein Eftevaag        esys context's linked list. We iterate through the list and search
1054*758e9fbaSOystein Eftevaag        for the corresponding object and return it if found.
1055*758e9fbaSOystein Eftevaag        If no object is found, this can be an erroneous handle number or it
1056*758e9fbaSOystein Eftevaag        can be because of a reference "global" object that does not require
1057*758e9fbaSOystein Eftevaag        previous initialization. */
1058*758e9fbaSOystein Eftevaag     for (esys_object_aux = esys_context->rsrc_list; esys_object_aux != NULL;
1059*758e9fbaSOystein Eftevaag          esys_object_aux = esys_object_aux->next) {
1060*758e9fbaSOystein Eftevaag         if (esys_object_aux->esys_handle == esys_handle) {
1061*758e9fbaSOystein Eftevaag             *esys_object = esys_object_aux;
1062*758e9fbaSOystein Eftevaag             return TPM2_RC_SUCCESS;
1063*758e9fbaSOystein Eftevaag         }
1064*758e9fbaSOystein Eftevaag     }
1065*758e9fbaSOystein Eftevaag 
1066*758e9fbaSOystein Eftevaag     /* All objects with a TR-handle larger than ESYS_TR_MIN_OBJECT must have
1067*758e9fbaSOystein Eftevaag        been initialized previously. Therefore the TR handle was erroneous. */
1068*758e9fbaSOystein Eftevaag     if (esys_handle >= ESYS_TR_MIN_OBJECT) {
1069*758e9fbaSOystein Eftevaag         LOG_ERROR("Error: Esys handle does not exist (%x).",
1070*758e9fbaSOystein Eftevaag                   TSS2_ESYS_RC_BAD_TR);
1071*758e9fbaSOystein Eftevaag         return TSS2_ESYS_RC_BAD_TR;
1072*758e9fbaSOystein Eftevaag     }
1073*758e9fbaSOystein Eftevaag 
1074*758e9fbaSOystein Eftevaag     /* There are special "global" object for the TPM, such as PCRs or
1075*758e9fbaSOystein Eftevaag        hierarchies. If they do not exist yet inside the Esys context we create
1076*758e9fbaSOystein Eftevaag        them here and return the newly created object. */
1077*758e9fbaSOystein Eftevaag     r = iesys_handle_to_tpm_handle(esys_handle, &tpm_handle);
1078*758e9fbaSOystein Eftevaag     return_if_error(r, "Unknown ESYS handle.");
1079*758e9fbaSOystein Eftevaag 
1080*758e9fbaSOystein Eftevaag     r = esys_CreateResourceObject(esys_context, esys_handle, &esys_object_aux);
1081*758e9fbaSOystein Eftevaag     return_if_error(r, "Creating Resource Object.");
1082*758e9fbaSOystein Eftevaag 
1083*758e9fbaSOystein Eftevaag     esys_object_aux->rsrc.handle = tpm_handle;
1084*758e9fbaSOystein Eftevaag     esys_object_aux->rsrc.rsrcType = IESYSC_WITHOUT_MISC_RSRC;
1085*758e9fbaSOystein Eftevaag 
1086*758e9fbaSOystein Eftevaag     r = Tss2_MU_TPM2_HANDLE_Marshal(tpm_handle,
1087*758e9fbaSOystein Eftevaag                                 &esys_object_aux->rsrc.name.name[0],
1088*758e9fbaSOystein Eftevaag                                 sizeof(esys_object_aux->rsrc.name.name),
1089*758e9fbaSOystein Eftevaag                                 &offset);
1090*758e9fbaSOystein Eftevaag     return_if_error(r, "Marshaling TPM handle.");
1091*758e9fbaSOystein Eftevaag 
1092*758e9fbaSOystein Eftevaag     esys_object_aux->rsrc.name.size = offset;
1093*758e9fbaSOystein Eftevaag     *esys_object = esys_object_aux;
1094*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
1095*758e9fbaSOystein Eftevaag }
1096*758e9fbaSOystein Eftevaag 
1097*758e9fbaSOystein Eftevaag /**
1098*758e9fbaSOystein Eftevaag  * Check that the esys context is ready for an _async call.
1099*758e9fbaSOystein Eftevaag  *
1100*758e9fbaSOystein Eftevaag  * This function will check that the sequence of invocations to the esys context
1101*758e9fbaSOystein Eftevaag  * was such that an _async function can be called. This means that the internal
1102*758e9fbaSOystein Eftevaag  * @state field is either @_ESYS_STATE_INIT, @_ESYS_STATE_ERRORRESPONSE,
1103*758e9fbaSOystein Eftevaag  * @_ESYS_STATE_FINISHED.
1104*758e9fbaSOystein Eftevaag  * @param[in,out] esys_context The esys context to issue the command on.
1105*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
1106*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_BAD_SEQUENCE if context is not ready for this function.
1107*758e9fbaSOystein Eftevaag  */
1108*758e9fbaSOystein Eftevaag TSS2_RC
iesys_check_sequence_async(ESYS_CONTEXT * esys_context)1109*758e9fbaSOystein Eftevaag iesys_check_sequence_async(ESYS_CONTEXT * esys_context)
1110*758e9fbaSOystein Eftevaag {
1111*758e9fbaSOystein Eftevaag     if (esys_context == NULL) {
1112*758e9fbaSOystein Eftevaag         LOG_ERROR("esyscontext is NULL.");
1113*758e9fbaSOystein Eftevaag         return TSS2_ESYS_RC_BAD_REFERENCE;
1114*758e9fbaSOystein Eftevaag     }
1115*758e9fbaSOystein Eftevaag 
1116*758e9fbaSOystein Eftevaag     if (esys_context->state != _ESYS_STATE_INIT &&
1117*758e9fbaSOystein Eftevaag         esys_context->state != _ESYS_STATE_RESUBMISSION) {
1118*758e9fbaSOystein Eftevaag         LOG_ERROR("Esys called in bad sequence.");
1119*758e9fbaSOystein Eftevaag         return TSS2_ESYS_RC_BAD_SEQUENCE;
1120*758e9fbaSOystein Eftevaag     }
1121*758e9fbaSOystein Eftevaag     esys_context->submissionCount = 1;
1122*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
1123*758e9fbaSOystein Eftevaag }
1124*758e9fbaSOystein Eftevaag 
1125*758e9fbaSOystein Eftevaag /** Check whether session without authorization occurs before one with.
1126*758e9fbaSOystein Eftevaag  *
1127*758e9fbaSOystein Eftevaag  * @param[in] session1-3 The three sessions.
1128*758e9fbaSOystein Eftevaag  * @retval TPM2_RC_SUCCESS if the order is ok.
1129*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_BAD_VALUE if not.
1130*758e9fbaSOystein Eftevaag  */
1131*758e9fbaSOystein Eftevaag TSS2_RC
check_session_feasibility(ESYS_TR shandle1,ESYS_TR shandle2,ESYS_TR shandle3,int mandatory)1132*758e9fbaSOystein Eftevaag check_session_feasibility(ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3,
1133*758e9fbaSOystein Eftevaag                           int mandatory)
1134*758e9fbaSOystein Eftevaag {
1135*758e9fbaSOystein Eftevaag     ESYS_TR handle_tab[3] = { shandle1, shandle2, shandle3 };
1136*758e9fbaSOystein Eftevaag     bool check_none = false;
1137*758e9fbaSOystein Eftevaag     for (int i = 2; i >= 0; i--) {
1138*758e9fbaSOystein Eftevaag         if (handle_tab[i] != ESYS_TR_NONE)
1139*758e9fbaSOystein Eftevaag             mandatory--;
1140*758e9fbaSOystein Eftevaag         if (handle_tab[i] != ESYS_TR_NONE && handle_tab[i] != ESYS_TR_PASSWORD)
1141*758e9fbaSOystein Eftevaag             check_none = true;
1142*758e9fbaSOystein Eftevaag         else {
1143*758e9fbaSOystein Eftevaag             if (check_none) {
1144*758e9fbaSOystein Eftevaag                 if (handle_tab[i] == ESYS_TR_NONE) {
1145*758e9fbaSOystein Eftevaag                     LOG_ERROR("Error: ESYS_TR_NONE used before other handle.");
1146*758e9fbaSOystein Eftevaag                     return TSS2_ESYS_RC_BAD_VALUE;
1147*758e9fbaSOystein Eftevaag                 }
1148*758e9fbaSOystein Eftevaag             }
1149*758e9fbaSOystein Eftevaag         }
1150*758e9fbaSOystein Eftevaag     }
1151*758e9fbaSOystein Eftevaag     if (mandatory > 0) {
1152*758e9fbaSOystein Eftevaag         LOG_ERROR("Not enough sessions provided for the command.");
1153*758e9fbaSOystein Eftevaag         return TSS2_ESYS_RC_BAD_VALUE;
1154*758e9fbaSOystein Eftevaag     }
1155*758e9fbaSOystein Eftevaag     return TPM2_RC_SUCCESS;
1156*758e9fbaSOystein Eftevaag }
1157*758e9fbaSOystein Eftevaag 
1158*758e9fbaSOystein Eftevaag /** Compute HMAC for a session.
1159*758e9fbaSOystein Eftevaag  *
1160*758e9fbaSOystein Eftevaag  * The HMAC is computed from the appropriate cp hash, the caller nonce, the TPM
1161*758e9fbaSOystein Eftevaag  * nonce and the session attributes. If an encrypt session is not the first
1162*758e9fbaSOystein Eftevaag  * session also the encrypt and the decrypt nonce have to be included.
1163*758e9fbaSOystein Eftevaag  * @param[in] session The session for which the HMAC has to be computed.
1164*758e9fbaSOystein Eftevaag  * @param[in] cp_hash_tab The table of computed cp hash values.
1165*758e9fbaSOystein Eftevaag  * @param[in] cpHashNum The number of computed cp hash values which depens on
1166*758e9fbaSOystein Eftevaag  *            the number of used hash algorithms.
1167*758e9fbaSOystein Eftevaag  * @param[in] encryptNonce The encrypt Nonce of an encryption session. Has to
1168*758e9fbaSOystein Eftevaag  *            be NULL if encryption session is first session.
1169*758e9fbaSOystein Eftevaag  * @param[in] decryptNonce The decrypt Nonce of an encryption session. Has to
1170*758e9fbaSOystein Eftevaag  *            be NULL if encryption session is first session.
1171*758e9fbaSOystein Eftevaag  * @param[out] auth The computed HMAC value.
1172*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
1173*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_MEMORY Memory can not be allocated.
1174*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_BAD_VALUE for invalid parameters.
1175*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_BAD_REFERENCE for unexpected NULL pointer parameters.
1176*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
1177*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_NOT_IMPLEMENTED if hash algorithm is not implemented.
1178*758e9fbaSOystein Eftevaag  * @retval TSS2_SYS_RC_* for SAPI errors.
1179*758e9fbaSOystein Eftevaag  */
1180*758e9fbaSOystein Eftevaag TSS2_RC
iesys_compute_hmac(RSRC_NODE_T * session,HASH_TAB_ITEM cp_hash_tab[3],uint8_t cpHashNum,TPM2B_NONCE * decryptNonce,TPM2B_NONCE * encryptNonce,TPMS_AUTH_COMMAND * auth)1181*758e9fbaSOystein Eftevaag iesys_compute_hmac(RSRC_NODE_T * session,
1182*758e9fbaSOystein Eftevaag                    HASH_TAB_ITEM cp_hash_tab[3],
1183*758e9fbaSOystein Eftevaag                    uint8_t cpHashNum,
1184*758e9fbaSOystein Eftevaag                    TPM2B_NONCE * decryptNonce,
1185*758e9fbaSOystein Eftevaag                    TPM2B_NONCE * encryptNonce,
1186*758e9fbaSOystein Eftevaag                    TPMS_AUTH_COMMAND * auth)
1187*758e9fbaSOystein Eftevaag {
1188*758e9fbaSOystein Eftevaag     TSS2_RC r;
1189*758e9fbaSOystein Eftevaag     size_t authHash_size = 0;
1190*758e9fbaSOystein Eftevaag 
1191*758e9fbaSOystein Eftevaag     if (session != NULL) {
1192*758e9fbaSOystein Eftevaag         IESYS_SESSION *rsrc_session = &session->rsrc.misc.rsrc_session;
1193*758e9fbaSOystein Eftevaag         r = iesys_crypto_hash_get_digest_size(rsrc_session->
1194*758e9fbaSOystein Eftevaag                                               authHash, &authHash_size);
1195*758e9fbaSOystein Eftevaag         return_if_error(r, "Initializing auth session");
1196*758e9fbaSOystein Eftevaag 
1197*758e9fbaSOystein Eftevaag         int hi = 0;
1198*758e9fbaSOystein Eftevaag         for (int j = 0; j < cpHashNum; j++) {
1199*758e9fbaSOystein Eftevaag             if (rsrc_session->authHash == cp_hash_tab[j].alg) {
1200*758e9fbaSOystein Eftevaag                 hi = j;
1201*758e9fbaSOystein Eftevaag                 break;
1202*758e9fbaSOystein Eftevaag             }
1203*758e9fbaSOystein Eftevaag         }
1204*758e9fbaSOystein Eftevaag         auth->hmac.size = sizeof(TPMU_HA);
1205*758e9fbaSOystein Eftevaag         /* if other than first session is used for for parameter encryption
1206*758e9fbaSOystein Eftevaag            the corresponding nonces have to be included into the hmac
1207*758e9fbaSOystein Eftevaag            computation of the first session */
1208*758e9fbaSOystein Eftevaag         r = iesys_crypto_authHmac(rsrc_session->authHash,
1209*758e9fbaSOystein Eftevaag                                   &rsrc_session->sessionValue[0],
1210*758e9fbaSOystein Eftevaag                                   rsrc_session->sizeHmacValue,
1211*758e9fbaSOystein Eftevaag                                   &cp_hash_tab[hi].digest[0],
1212*758e9fbaSOystein Eftevaag                                   cp_hash_tab[hi].size,
1213*758e9fbaSOystein Eftevaag                                   &rsrc_session->nonceCaller,
1214*758e9fbaSOystein Eftevaag                                   &rsrc_session->nonceTPM,
1215*758e9fbaSOystein Eftevaag                                   decryptNonce, encryptNonce,
1216*758e9fbaSOystein Eftevaag                                   rsrc_session->sessionAttributes, &auth->hmac);
1217*758e9fbaSOystein Eftevaag         return_if_error(r, "HMAC error");
1218*758e9fbaSOystein Eftevaag         auth->sessionHandle = session->rsrc.handle;
1219*758e9fbaSOystein Eftevaag         auth->nonce = rsrc_session->nonceCaller;
1220*758e9fbaSOystein Eftevaag         auth->sessionAttributes =
1221*758e9fbaSOystein Eftevaag             rsrc_session->sessionAttributes;
1222*758e9fbaSOystein Eftevaag     }
1223*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
1224*758e9fbaSOystein Eftevaag }
1225*758e9fbaSOystein Eftevaag 
1226*758e9fbaSOystein Eftevaag /** Compute the auth values (HMACs) for all sessions.
1227*758e9fbaSOystein Eftevaag  *
1228*758e9fbaSOystein Eftevaag  * The caller nonce, the encrypt nonces, the cp hashes, and the HMAC values for
1229*758e9fbaSOystein Eftevaag  * the command authorization are computed.
1230*758e9fbaSOystein Eftevaag  * @param[in] esys_context The esys context to issue the command on.
1231*758e9fbaSOystein Eftevaag  * @param[in] h1-3 The esys session resource objects.
1232*758e9fbaSOystein Eftevaag  * @param[out] The list if the authorizations with the computed HMACs.
1233*758e9fbaSOystein Eftevaag  * @param[out] auth The computed HMAC value.
1234*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
1235*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_MEMORY Memory can not be allocated.
1236*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_BAD_VALUE for invalid parameters.
1237*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_BAD_REFERENCE for unexpected NULL pointer parameters.
1238*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
1239*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_NOT_IMPLEMENTED if hash algorithm is not implemented.
1240*758e9fbaSOystein Eftevaag  * @retval TSS2_SYS_RC_* for SAPI errors.
1241*758e9fbaSOystein Eftevaag  */
1242*758e9fbaSOystein Eftevaag TSS2_RC
iesys_gen_auths(ESYS_CONTEXT * esys_context,RSRC_NODE_T * h1,RSRC_NODE_T * h2,RSRC_NODE_T * h3,TSS2L_SYS_AUTH_COMMAND * auths)1243*758e9fbaSOystein Eftevaag iesys_gen_auths(ESYS_CONTEXT * esys_context,
1244*758e9fbaSOystein Eftevaag                 RSRC_NODE_T * h1,
1245*758e9fbaSOystein Eftevaag                 RSRC_NODE_T * h2,
1246*758e9fbaSOystein Eftevaag                 RSRC_NODE_T * h3,
1247*758e9fbaSOystein Eftevaag                 TSS2L_SYS_AUTH_COMMAND * auths)
1248*758e9fbaSOystein Eftevaag {
1249*758e9fbaSOystein Eftevaag     TSS2_RC r;
1250*758e9fbaSOystein Eftevaag     TPM2B_NONCE *decryptNonce = NULL;
1251*758e9fbaSOystein Eftevaag     int decryptNonceIdx = 0;
1252*758e9fbaSOystein Eftevaag     int encryptNonceIdx = 0;
1253*758e9fbaSOystein Eftevaag     TPM2B_NONCE *encryptNonce = NULL;
1254*758e9fbaSOystein Eftevaag 
1255*758e9fbaSOystein Eftevaag     RSRC_NODE_T *objects[] = { h1, h2, h3 };
1256*758e9fbaSOystein Eftevaag 
1257*758e9fbaSOystein Eftevaag     HASH_TAB_ITEM cp_hash_tab[3];
1258*758e9fbaSOystein Eftevaag     uint8_t cpHashNum = 0;
1259*758e9fbaSOystein Eftevaag 
1260*758e9fbaSOystein Eftevaag     auths->count = 0;
1261*758e9fbaSOystein Eftevaag     r = iesys_gen_caller_nonces(esys_context);
1262*758e9fbaSOystein Eftevaag     return_if_error(r, "Error nonce generation caller");
1263*758e9fbaSOystein Eftevaag     r = iesys_encrypt_param(esys_context, &decryptNonce, &decryptNonceIdx);
1264*758e9fbaSOystein Eftevaag     return_if_error(r, "Error parameter encryption");
1265*758e9fbaSOystein Eftevaag     r = iesys_compute_encrypt_nonce(esys_context, &encryptNonceIdx,
1266*758e9fbaSOystein Eftevaag                                     &encryptNonce);
1267*758e9fbaSOystein Eftevaag     return_if_error(r, "More than one crypt session");
1268*758e9fbaSOystein Eftevaag 
1269*758e9fbaSOystein Eftevaag     /* Compute cp hash values for command buffer for all used algorithms */
1270*758e9fbaSOystein Eftevaag 
1271*758e9fbaSOystein Eftevaag     r = iesys_compute_cp_hashtab(esys_context,
1272*758e9fbaSOystein Eftevaag                                  (h1 != NULL) ? &h1->rsrc.name : NULL,
1273*758e9fbaSOystein Eftevaag                                  (h2 != NULL) ? &h2->rsrc.name : NULL,
1274*758e9fbaSOystein Eftevaag                                  (h3 != NULL) ? &h3->rsrc.name : NULL,
1275*758e9fbaSOystein Eftevaag                                  &cp_hash_tab[0], &cpHashNum);
1276*758e9fbaSOystein Eftevaag     return_if_error(r, "Error while computing cp hashes");
1277*758e9fbaSOystein Eftevaag 
1278*758e9fbaSOystein Eftevaag     for (int session_idx = 0; session_idx < 3; session_idx++) {
1279*758e9fbaSOystein Eftevaag         auths->auths[auths->count].nonce.size = 0;
1280*758e9fbaSOystein Eftevaag         auths->auths[auths->count].sessionAttributes = 0;
1281*758e9fbaSOystein Eftevaag         if (esys_context->session_type[session_idx] == ESYS_TR_PASSWORD) {
1282*758e9fbaSOystein Eftevaag             if (objects[session_idx] == NULL) {
1283*758e9fbaSOystein Eftevaag                 auths->auths[auths->count].hmac.size = 0;
1284*758e9fbaSOystein Eftevaag                 auths->count += 1;
1285*758e9fbaSOystein Eftevaag             } else {
1286*758e9fbaSOystein Eftevaag                 auths->auths[auths->count].sessionHandle = TPM2_RS_PW;
1287*758e9fbaSOystein Eftevaag                 auths->auths[auths->count].hmac = objects[session_idx]->auth;
1288*758e9fbaSOystein Eftevaag                 auths->count += 1;
1289*758e9fbaSOystein Eftevaag             }
1290*758e9fbaSOystein Eftevaag             continue;
1291*758e9fbaSOystein Eftevaag         }
1292*758e9fbaSOystein Eftevaag         RSRC_NODE_T *session = esys_context->session_tab[session_idx];
1293*758e9fbaSOystein Eftevaag         if (session != NULL) {
1294*758e9fbaSOystein Eftevaag             IESYS_SESSION *rsrc_session = &session->rsrc.misc.rsrc_session;
1295*758e9fbaSOystein Eftevaag             if (rsrc_session->type_policy_session == POLICY_PASSWORD) {
1296*758e9fbaSOystein Eftevaag                 auths->auths[auths->count].sessionHandle = session->rsrc.handle;
1297*758e9fbaSOystein Eftevaag                 if (objects[session_idx] == NULL) {
1298*758e9fbaSOystein Eftevaag                     auths->auths[auths->count].hmac.size = 0;
1299*758e9fbaSOystein Eftevaag                 } else {
1300*758e9fbaSOystein Eftevaag                     auths->auths[auths->count].hmac = objects[session_idx]->auth;
1301*758e9fbaSOystein Eftevaag                 }
1302*758e9fbaSOystein Eftevaag                 auths->auths[auths->count].sessionAttributes =
1303*758e9fbaSOystein Eftevaag                     session->rsrc.misc.rsrc_session.sessionAttributes;
1304*758e9fbaSOystein Eftevaag                 auths->count += 1;
1305*758e9fbaSOystein Eftevaag                 continue;
1306*758e9fbaSOystein Eftevaag             }
1307*758e9fbaSOystein Eftevaag         }
1308*758e9fbaSOystein Eftevaag         r = iesys_compute_hmac(esys_context->session_tab[session_idx],
1309*758e9fbaSOystein Eftevaag                                &cp_hash_tab[0], cpHashNum,
1310*758e9fbaSOystein Eftevaag                                (session_idx == 0
1311*758e9fbaSOystein Eftevaag                                 && decryptNonceIdx > 0) ? decryptNonce : NULL,
1312*758e9fbaSOystein Eftevaag                                (session_idx == 0
1313*758e9fbaSOystein Eftevaag                                 && encryptNonceIdx > 0) ? encryptNonce : NULL,
1314*758e9fbaSOystein Eftevaag                                &auths->auths[session_idx]);
1315*758e9fbaSOystein Eftevaag         return_if_error(r, "Error while computing hmacs");
1316*758e9fbaSOystein Eftevaag         if (esys_context->session_tab[session_idx] != NULL) {
1317*758e9fbaSOystein Eftevaag             auths->auths[auths->count].sessionHandle = session->rsrc.handle;
1318*758e9fbaSOystein Eftevaag             auths->count++;
1319*758e9fbaSOystein Eftevaag         }
1320*758e9fbaSOystein Eftevaag     }
1321*758e9fbaSOystein Eftevaag 
1322*758e9fbaSOystein Eftevaag     esys_context->encryptNonceIdx = encryptNonceIdx;
1323*758e9fbaSOystein Eftevaag     esys_context->encryptNonce = encryptNonce;
1324*758e9fbaSOystein Eftevaag 
1325*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
1326*758e9fbaSOystein Eftevaag }
1327*758e9fbaSOystein Eftevaag 
1328*758e9fbaSOystein Eftevaag /** Check the response HMACs for all sessions.
1329*758e9fbaSOystein Eftevaag  *
1330*758e9fbaSOystein Eftevaag  * The response HMAC values are computed. Based on these values the HMACs for
1331*758e9fbaSOystein Eftevaag  * all sessions are computed and compared with the HMACs stored in the response
1332*758e9fbaSOystein Eftevaag  * auth list which is determined with the SAPI function Tss2_Sys_GetRspAuths.
1333*758e9fbaSOystein Eftevaag  * @param[in] esys_context The esys context which is used to get the response
1334*758e9fbaSOystein Eftevaag  * auth values and the sessions.
1335*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
1336*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_MEMORY Memory can not be allocated.
1337*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_BAD_VALUE for invalid parameters.
1338*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_BAD_REFERENCE for unexpected NULL pointer parameters.
1339*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
1340*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_NOT_IMPLEMENTED if hash algorithm is not implemented.
1341*758e9fbaSOystein Eftevaag  * @retval TSS2_SYS_RC_* for SAPI errors.
1342*758e9fbaSOystein Eftevaag  */
1343*758e9fbaSOystein Eftevaag TSS2_RC
iesys_check_response(ESYS_CONTEXT * esys_context)1344*758e9fbaSOystein Eftevaag iesys_check_response(ESYS_CONTEXT * esys_context)
1345*758e9fbaSOystein Eftevaag {
1346*758e9fbaSOystein Eftevaag     TSS2_RC r;
1347*758e9fbaSOystein Eftevaag     const uint8_t *rpBuffer;
1348*758e9fbaSOystein Eftevaag     size_t rpBuffer_size;
1349*758e9fbaSOystein Eftevaag     TSS2L_SYS_AUTH_RESPONSE rspAuths;
1350*758e9fbaSOystein Eftevaag     HASH_TAB_ITEM rp_hash_tab[3];
1351*758e9fbaSOystein Eftevaag     uint8_t rpHashNum = 0;
1352*758e9fbaSOystein Eftevaag 
1353*758e9fbaSOystein Eftevaag     if (esys_context->authsCount == 0) {
1354*758e9fbaSOystein Eftevaag         LOG_TRACE("No auths to verify");
1355*758e9fbaSOystein Eftevaag         return TSS2_RC_SUCCESS;
1356*758e9fbaSOystein Eftevaag     }
1357*758e9fbaSOystein Eftevaag 
1358*758e9fbaSOystein Eftevaag     r = Tss2_Sys_GetRspAuths(esys_context->sys, &rspAuths);
1359*758e9fbaSOystein Eftevaag     return_if_error(r, "Error: GetRspAuths");
1360*758e9fbaSOystein Eftevaag 
1361*758e9fbaSOystein Eftevaag     if (rspAuths.count != esys_context->authsCount) {
1362*758e9fbaSOystein Eftevaag         LOG_ERROR("Number of response auths differs: %i (expected %i)",
1363*758e9fbaSOystein Eftevaag                   rspAuths.count, esys_context->authsCount);
1364*758e9fbaSOystein Eftevaag         return TSS2_ESYS_RC_GENERAL_FAILURE;
1365*758e9fbaSOystein Eftevaag     }
1366*758e9fbaSOystein Eftevaag     /*
1367*758e9fbaSOystein Eftevaag      * At least one session object is defined so the rp hashes must be computed
1368*758e9fbaSOystein Eftevaag      * and the HMACs of the responses have to be checked.
1369*758e9fbaSOystein Eftevaag      * Encrypted response parameters will be decrypted.
1370*758e9fbaSOystein Eftevaag      */
1371*758e9fbaSOystein Eftevaag     if (esys_context->session_type[0] >= ESYS_TR_MIN_OBJECT ||
1372*758e9fbaSOystein Eftevaag         esys_context->session_type[1] >= ESYS_TR_MIN_OBJECT ||
1373*758e9fbaSOystein Eftevaag         esys_context->session_type[2] >= ESYS_TR_MIN_OBJECT) {
1374*758e9fbaSOystein Eftevaag         r = Tss2_Sys_GetRpBuffer(esys_context->sys, &rpBuffer_size, &rpBuffer);
1375*758e9fbaSOystein Eftevaag         return_if_error(r, "Error: get rp buffer");
1376*758e9fbaSOystein Eftevaag 
1377*758e9fbaSOystein Eftevaag         r = iesys_compute_rp_hashtab(esys_context,
1378*758e9fbaSOystein Eftevaag                                      rpBuffer, rpBuffer_size,
1379*758e9fbaSOystein Eftevaag                                      &rp_hash_tab[0], &rpHashNum);
1380*758e9fbaSOystein Eftevaag         return_if_error(r, "Error: while computing response hashes");
1381*758e9fbaSOystein Eftevaag 
1382*758e9fbaSOystein Eftevaag         r = iesys_check_rp_hmacs(esys_context, &rspAuths, &rp_hash_tab[0],
1383*758e9fbaSOystein Eftevaag                                  rpHashNum);
1384*758e9fbaSOystein Eftevaag         return_if_error(r, "Error: response hmac check");
1385*758e9fbaSOystein Eftevaag 
1386*758e9fbaSOystein Eftevaag         if (esys_context->encryptNonce == NULL) {
1387*758e9fbaSOystein Eftevaag             iesys_restore_session_flags(esys_context);
1388*758e9fbaSOystein Eftevaag             return TSS2_RC_SUCCESS;
1389*758e9fbaSOystein Eftevaag         }
1390*758e9fbaSOystein Eftevaag 
1391*758e9fbaSOystein Eftevaag         r = iesys_decrypt_param(esys_context);
1392*758e9fbaSOystein Eftevaag         return_if_error(r, "Error: while decrypting parameter.");
1393*758e9fbaSOystein Eftevaag         iesys_restore_session_flags(esys_context);
1394*758e9fbaSOystein Eftevaag 
1395*758e9fbaSOystein Eftevaag     }
1396*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
1397*758e9fbaSOystein Eftevaag }
1398*758e9fbaSOystein Eftevaag 
1399*758e9fbaSOystein Eftevaag /** Compute the name from the public data of a NV index.
1400*758e9fbaSOystein Eftevaag  *
1401*758e9fbaSOystein Eftevaag  * The name of a NV index is computed as follows:
1402*758e9fbaSOystein Eftevaag  *   name =  nameAlg||Hash(nameAlg,marshal(publicArea))
1403*758e9fbaSOystein Eftevaag  * @param[in] publicInfo The public information of the NV index.
1404*758e9fbaSOystein Eftevaag  * @param[out] name The computed name.
1405*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
1406*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_MEMORY Memory can not be allocated.
1407*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_BAD_VALUE for invalid parameters.
1408*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_BAD_REFERENCE for unexpected NULL pointer parameters.
1409*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
1410*758e9fbaSOystein Eftevaag  * @retval TSS2_ESYS_RC_NOT_IMPLEMENTED if hash algorithm is not implemented.
1411*758e9fbaSOystein Eftevaag  * @retval TSS2_SYS_RC_* for SAPI errors.
1412*758e9fbaSOystein Eftevaag  */
1413*758e9fbaSOystein Eftevaag TSS2_RC
iesys_nv_get_name(TPM2B_NV_PUBLIC * publicInfo,TPM2B_NAME * name)1414*758e9fbaSOystein Eftevaag iesys_nv_get_name(TPM2B_NV_PUBLIC * publicInfo, TPM2B_NAME * name)
1415*758e9fbaSOystein Eftevaag {
1416*758e9fbaSOystein Eftevaag     BYTE buffer[sizeof(TPMS_NV_PUBLIC)];
1417*758e9fbaSOystein Eftevaag     size_t offset = 0;
1418*758e9fbaSOystein Eftevaag     size_t size = sizeof(TPMU_NAME) - sizeof(TPMI_ALG_HASH);
1419*758e9fbaSOystein Eftevaag     size_t len_alg_id = sizeof(TPMI_ALG_HASH);
1420*758e9fbaSOystein Eftevaag     IESYS_CRYPTO_CONTEXT_BLOB *cryptoContext;
1421*758e9fbaSOystein Eftevaag 
1422*758e9fbaSOystein Eftevaag     if (publicInfo->nvPublic.nameAlg == TPM2_ALG_NULL) {
1423*758e9fbaSOystein Eftevaag         name->size = 0;
1424*758e9fbaSOystein Eftevaag         return TSS2_RC_SUCCESS;
1425*758e9fbaSOystein Eftevaag     }
1426*758e9fbaSOystein Eftevaag     TSS2_RC r;
1427*758e9fbaSOystein Eftevaag     r = iesys_crypto_hash_start(&cryptoContext, publicInfo->nvPublic.nameAlg);
1428*758e9fbaSOystein Eftevaag     return_if_error(r, "Crypto hash start");
1429*758e9fbaSOystein Eftevaag 
1430*758e9fbaSOystein Eftevaag     r = Tss2_MU_TPMS_NV_PUBLIC_Marshal(&publicInfo->nvPublic,
1431*758e9fbaSOystein Eftevaag                                        &buffer[0], sizeof(TPMS_NV_PUBLIC),
1432*758e9fbaSOystein Eftevaag                                        &offset);
1433*758e9fbaSOystein Eftevaag     goto_if_error(r, "Marshaling TPMS_NV_PUBLIC", error_cleanup);
1434*758e9fbaSOystein Eftevaag 
1435*758e9fbaSOystein Eftevaag     r = iesys_crypto_hash_update(cryptoContext, &buffer[0], offset);
1436*758e9fbaSOystein Eftevaag     goto_if_error(r, "crypto hash update", error_cleanup);
1437*758e9fbaSOystein Eftevaag 
1438*758e9fbaSOystein Eftevaag     r = iesys_crypto_hash_finish(&cryptoContext, &name->name[len_alg_id],
1439*758e9fbaSOystein Eftevaag                                      &size);
1440*758e9fbaSOystein Eftevaag     goto_if_error(r, "crypto hash finish", error_cleanup);
1441*758e9fbaSOystein Eftevaag 
1442*758e9fbaSOystein Eftevaag     offset = 0;
1443*758e9fbaSOystein Eftevaag     r = Tss2_MU_TPMI_ALG_HASH_Marshal(publicInfo->nvPublic.nameAlg,
1444*758e9fbaSOystein Eftevaag                                   &name->name[0], sizeof(TPMI_ALG_HASH),
1445*758e9fbaSOystein Eftevaag                                   &offset);
1446*758e9fbaSOystein Eftevaag     goto_if_error(r, "Marshaling TPMI_ALG_HASH", error_cleanup);
1447*758e9fbaSOystein Eftevaag 
1448*758e9fbaSOystein Eftevaag     name->size = size + len_alg_id;
1449*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
1450*758e9fbaSOystein Eftevaag 
1451*758e9fbaSOystein Eftevaag error_cleanup:
1452*758e9fbaSOystein Eftevaag     if (cryptoContext)
1453*758e9fbaSOystein Eftevaag         iesys_crypto_hash_abort(&cryptoContext);
1454*758e9fbaSOystein Eftevaag     return r;
1455*758e9fbaSOystein Eftevaag }
1456*758e9fbaSOystein Eftevaag 
1457*758e9fbaSOystein Eftevaag /** Compute the name of a TPM transient or persistent object.
1458*758e9fbaSOystein Eftevaag  *
1459*758e9fbaSOystein Eftevaag  * The name of a NV index is computed as follows:
1460*758e9fbaSOystein Eftevaag  *   name = Hash(nameAlg,marshal(publicArea))
1461*758e9fbaSOystein Eftevaag  * @param[in] publicInfo The public information of the TPM object.
1462*758e9fbaSOystein Eftevaag  * @param[out] name The computed name.
1463*758e9fbaSOystein Eftevaag  * @retval TPM2_RC_SUCCESS  or one of the possible errors TSS2_ESYS_RC_BAD_VALUE,
1464*758e9fbaSOystein Eftevaag  * TSS2_ESYS_RC_MEMORY, TSS2_ESYS_RC_GENERAL_FAILURE, TSS2_ESYS_RC_NOT_IMPLEMENTED,
1465*758e9fbaSOystein Eftevaag  * or return codes of SAPI errors.
1466*758e9fbaSOystein Eftevaag  */
1467*758e9fbaSOystein Eftevaag TSS2_RC
iesys_get_name(TPM2B_PUBLIC * publicInfo,TPM2B_NAME * name)1468*758e9fbaSOystein Eftevaag iesys_get_name(TPM2B_PUBLIC * publicInfo, TPM2B_NAME * name)
1469*758e9fbaSOystein Eftevaag {
1470*758e9fbaSOystein Eftevaag     BYTE buffer[sizeof(TPMT_PUBLIC)];
1471*758e9fbaSOystein Eftevaag     size_t offset = 0;
1472*758e9fbaSOystein Eftevaag     size_t len_alg_id = sizeof(TPMI_ALG_HASH);
1473*758e9fbaSOystein Eftevaag     size_t size = sizeof(TPMU_NAME) - sizeof(TPMI_ALG_HASH);
1474*758e9fbaSOystein Eftevaag     IESYS_CRYPTO_CONTEXT_BLOB *cryptoContext;
1475*758e9fbaSOystein Eftevaag 
1476*758e9fbaSOystein Eftevaag     if (publicInfo->publicArea.nameAlg == TPM2_ALG_NULL) {
1477*758e9fbaSOystein Eftevaag         name->size = 0;
1478*758e9fbaSOystein Eftevaag         return TSS2_RC_SUCCESS;
1479*758e9fbaSOystein Eftevaag     }
1480*758e9fbaSOystein Eftevaag     TSS2_RC r;
1481*758e9fbaSOystein Eftevaag     r = iesys_crypto_hash_start(&cryptoContext, publicInfo->publicArea.nameAlg);
1482*758e9fbaSOystein Eftevaag     return_if_error(r, "crypto hash start");
1483*758e9fbaSOystein Eftevaag 
1484*758e9fbaSOystein Eftevaag     r = Tss2_MU_TPMT_PUBLIC_Marshal(&publicInfo->publicArea,
1485*758e9fbaSOystein Eftevaag                                     &buffer[0], sizeof(TPMT_PUBLIC), &offset);
1486*758e9fbaSOystein Eftevaag     goto_if_error(r, "Marshaling TPMT_PUBLIC", error_cleanup);
1487*758e9fbaSOystein Eftevaag 
1488*758e9fbaSOystein Eftevaag     r = iesys_crypto_hash_update(cryptoContext, &buffer[0], offset);
1489*758e9fbaSOystein Eftevaag     goto_if_error(r, "crypto hash update", error_cleanup);
1490*758e9fbaSOystein Eftevaag 
1491*758e9fbaSOystein Eftevaag     r = iesys_crypto_hash_finish(&cryptoContext, &name->name[len_alg_id],
1492*758e9fbaSOystein Eftevaag                                      &size);
1493*758e9fbaSOystein Eftevaag     goto_if_error(r, "crypto hash finish", error_cleanup);
1494*758e9fbaSOystein Eftevaag 
1495*758e9fbaSOystein Eftevaag     offset = 0;
1496*758e9fbaSOystein Eftevaag     r = Tss2_MU_TPMI_ALG_HASH_Marshal(publicInfo->publicArea.nameAlg,
1497*758e9fbaSOystein Eftevaag                                   &name->name[0], sizeof(TPMI_ALG_HASH),
1498*758e9fbaSOystein Eftevaag                                   &offset);
1499*758e9fbaSOystein Eftevaag     goto_if_error(r, "Marshaling TPMI_ALG_HASH", error_cleanup);
1500*758e9fbaSOystein Eftevaag 
1501*758e9fbaSOystein Eftevaag     name->size = size + len_alg_id;
1502*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
1503*758e9fbaSOystein Eftevaag 
1504*758e9fbaSOystein Eftevaag error_cleanup:
1505*758e9fbaSOystein Eftevaag     if (cryptoContext)
1506*758e9fbaSOystein Eftevaag         iesys_crypto_hash_abort(&cryptoContext);
1507*758e9fbaSOystein Eftevaag     return r;
1508*758e9fbaSOystein Eftevaag }
1509*758e9fbaSOystein Eftevaag 
1510*758e9fbaSOystein Eftevaag /** Check whether the return code corresponds to an TPM error.
1511*758e9fbaSOystein Eftevaag  *
1512*758e9fbaSOystein Eftevaag  * if no layer is part of the return code or a layer from the resource manager
1513*758e9fbaSOystein Eftevaag  * is given the function will return true.
1514*758e9fbaSOystein Eftevaag  * @param[in] r The return code to be checked.
1515*758e9fbaSOystein Eftevaag  * @retval true if r corresponds to an TPM error.
1516*758e9fbaSOystein Eftevaag  * @retval false in other cases.
1517*758e9fbaSOystein Eftevaag  */
1518*758e9fbaSOystein Eftevaag bool
iesys_tpm_error(TSS2_RC r)1519*758e9fbaSOystein Eftevaag iesys_tpm_error(TSS2_RC r)
1520*758e9fbaSOystein Eftevaag {
1521*758e9fbaSOystein Eftevaag     return (r != TSS2_RC_SUCCESS &&
1522*758e9fbaSOystein Eftevaag             ((r & TSS2_RC_LAYER_MASK) == 0 ||
1523*758e9fbaSOystein Eftevaag              (r & TSS2_RC_LAYER_MASK) == TSS2_RESMGR_TPM_RC_LAYER ||
1524*758e9fbaSOystein Eftevaag              (r & TSS2_RC_LAYER_MASK) == TSS2_RESMGR_RC_LAYER));
1525*758e9fbaSOystein Eftevaag }
1526