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 ¶m_size, ¶m_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 ¶m_size, ¶m_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, ¶mSize,
679*758e9fbaSOystein Eftevaag ¶mBuffer);
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