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
7*758e9fbaSOystein Eftevaag #ifdef HAVE_CONFIG_H
8*758e9fbaSOystein Eftevaag #include <config.h>
9*758e9fbaSOystein Eftevaag #endif
10*758e9fbaSOystein Eftevaag
11*758e9fbaSOystein Eftevaag #include <gcrypt.h>
12*758e9fbaSOystein Eftevaag #include <stdio.h>
13*758e9fbaSOystein Eftevaag
14*758e9fbaSOystein Eftevaag #include "tss2_esys.h"
15*758e9fbaSOystein Eftevaag
16*758e9fbaSOystein Eftevaag #include "esys_crypto.h"
17*758e9fbaSOystein Eftevaag #include "esys_iutil.h"
18*758e9fbaSOystein Eftevaag #include "esys_mu.h"
19*758e9fbaSOystein Eftevaag #define LOGMODULE esys_crypto
20*758e9fbaSOystein Eftevaag #include "util/log.h"
21*758e9fbaSOystein Eftevaag #include "util/aux_util.h"
22*758e9fbaSOystein Eftevaag
23*758e9fbaSOystein Eftevaag /** Context to hold temporary values for iesys_crypto */
24*758e9fbaSOystein Eftevaag typedef struct _IESYS_CRYPTO_CONTEXT {
25*758e9fbaSOystein Eftevaag enum {
26*758e9fbaSOystein Eftevaag IESYS_CRYPTOGCRY_TYPE_HASH = 1,
27*758e9fbaSOystein Eftevaag IESYS_CRYPTOGCRY_TYPE_HMAC,
28*758e9fbaSOystein Eftevaag } type; /**< The type of context to hold; hash or hmac */
29*758e9fbaSOystein Eftevaag union {
30*758e9fbaSOystein Eftevaag struct {
31*758e9fbaSOystein Eftevaag gcry_md_hd_t gcry_context;
32*758e9fbaSOystein Eftevaag int gcry_hash_alg;
33*758e9fbaSOystein Eftevaag size_t hash_len;
34*758e9fbaSOystein Eftevaag } hash; /**< the state variables for a hash context */
35*758e9fbaSOystein Eftevaag struct {
36*758e9fbaSOystein Eftevaag gcry_mac_hd_t gcry_context;
37*758e9fbaSOystein Eftevaag int gcry_hmac_alg;
38*758e9fbaSOystein Eftevaag size_t hmac_len;
39*758e9fbaSOystein Eftevaag } hmac; /**< the state variables for an hmac context */
40*758e9fbaSOystein Eftevaag };
41*758e9fbaSOystein Eftevaag } IESYS_CRYPTOGCRY_CONTEXT;
42*758e9fbaSOystein Eftevaag
43*758e9fbaSOystein Eftevaag
44*758e9fbaSOystein Eftevaag /* Convert gcrypt mpi number to binary with fixed length */
mpi2bin(gcry_mpi_t mpi,unsigned char * bin,size_t bin_length,size_t max_out_size)45*758e9fbaSOystein Eftevaag static gcry_error_t mpi2bin(gcry_mpi_t mpi, unsigned char *bin,
46*758e9fbaSOystein Eftevaag size_t bin_length, size_t max_out_size)
47*758e9fbaSOystein Eftevaag {
48*758e9fbaSOystein Eftevaag gcry_error_t err;
49*758e9fbaSOystein Eftevaag size_t size;
50*758e9fbaSOystein Eftevaag size_t offset;
51*758e9fbaSOystein Eftevaag
52*758e9fbaSOystein Eftevaag /* Determine size of mpi */
53*758e9fbaSOystein Eftevaag err = gcry_mpi_print(GCRYMPI_FMT_USG, NULL, max_out_size, &size, mpi);
54*758e9fbaSOystein Eftevaag if (err != GPG_ERR_NO_ERROR) {
55*758e9fbaSOystein Eftevaag LOG_ERROR("Function gcry_mpi_print");
56*758e9fbaSOystein Eftevaag return err;
57*758e9fbaSOystein Eftevaag }
58*758e9fbaSOystein Eftevaag
59*758e9fbaSOystein Eftevaag offset = bin_length - size;
60*758e9fbaSOystein Eftevaag memset(&bin[0], 0,offset);
61*758e9fbaSOystein Eftevaag err = gcry_mpi_print(GCRYMPI_FMT_USG, &bin[offset], bin_length - offset, &size, mpi);
62*758e9fbaSOystein Eftevaag if (err != GPG_ERR_NO_ERROR) {
63*758e9fbaSOystein Eftevaag LOG_ERROR("Function gcry_mpi_print");
64*758e9fbaSOystein Eftevaag }
65*758e9fbaSOystein Eftevaag return err;
66*758e9fbaSOystein Eftevaag }
67*758e9fbaSOystein Eftevaag
68*758e9fbaSOystein Eftevaag /** Provide the context for the computation of a hash digest.
69*758e9fbaSOystein Eftevaag *
70*758e9fbaSOystein Eftevaag * The context will be created and initialized according to the hash function.
71*758e9fbaSOystein Eftevaag * @param[out] context The created context (callee-allocated).
72*758e9fbaSOystein Eftevaag * @param[in] hashAlg The hash algorithm for the creation of the context.
73*758e9fbaSOystein Eftevaag * @retval TSS2_RC_SUCCESS on success.
74*758e9fbaSOystein Eftevaag * @retval TSS2_ESYS_RC_BAD_VALUE or TSS2_ESYS_RC_BAD_REFERENCE for invalid parameters.
75*758e9fbaSOystein Eftevaag * @retval TSS2_ESYS_RC_MEMORY Memory cannot be allocated.
76*758e9fbaSOystein Eftevaag * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
77*758e9fbaSOystein Eftevaag */
78*758e9fbaSOystein Eftevaag TSS2_RC
iesys_cryptogcry_hash_start(IESYS_CRYPTO_CONTEXT_BLOB ** context,TPM2_ALG_ID hashAlg)79*758e9fbaSOystein Eftevaag iesys_cryptogcry_hash_start(IESYS_CRYPTO_CONTEXT_BLOB ** context,
80*758e9fbaSOystein Eftevaag TPM2_ALG_ID hashAlg)
81*758e9fbaSOystein Eftevaag {
82*758e9fbaSOystein Eftevaag LOG_TRACE("call: context=%p hashAlg=%"PRIu16, context, hashAlg);
83*758e9fbaSOystein Eftevaag return_if_null(context, "Context is NULL", TSS2_ESYS_RC_BAD_REFERENCE);
84*758e9fbaSOystein Eftevaag
85*758e9fbaSOystein Eftevaag IESYS_CRYPTOGCRY_CONTEXT *mycontext;
86*758e9fbaSOystein Eftevaag mycontext = calloc(1, sizeof(IESYS_CRYPTOGCRY_CONTEXT));
87*758e9fbaSOystein Eftevaag return_if_null(mycontext, "Out of Memory", TSS2_ESYS_RC_MEMORY);
88*758e9fbaSOystein Eftevaag
89*758e9fbaSOystein Eftevaag mycontext->type = IESYS_CRYPTOGCRY_TYPE_HASH;
90*758e9fbaSOystein Eftevaag
91*758e9fbaSOystein Eftevaag switch (hashAlg) {
92*758e9fbaSOystein Eftevaag case TPM2_ALG_SHA1:
93*758e9fbaSOystein Eftevaag mycontext->hash.gcry_hash_alg = GCRY_MD_SHA1;
94*758e9fbaSOystein Eftevaag break;
95*758e9fbaSOystein Eftevaag case TPM2_ALG_SHA256:
96*758e9fbaSOystein Eftevaag mycontext->hash.gcry_hash_alg = GCRY_MD_SHA256;
97*758e9fbaSOystein Eftevaag break;
98*758e9fbaSOystein Eftevaag case TPM2_ALG_SHA384:
99*758e9fbaSOystein Eftevaag mycontext->hash.gcry_hash_alg = GCRY_MD_SHA384;
100*758e9fbaSOystein Eftevaag break;
101*758e9fbaSOystein Eftevaag default:
102*758e9fbaSOystein Eftevaag LOG_ERROR("Unsupported hash algorithm (%"PRIu16")", hashAlg);
103*758e9fbaSOystein Eftevaag free(mycontext);
104*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_NOT_IMPLEMENTED;
105*758e9fbaSOystein Eftevaag }
106*758e9fbaSOystein Eftevaag int hash_len = gcry_md_get_algo_dlen(mycontext->hash.gcry_hash_alg);
107*758e9fbaSOystein Eftevaag if (hash_len <= 0) {
108*758e9fbaSOystein Eftevaag LOG_ERROR("Unsupported hash algorithm (%"PRIu16")", hashAlg);
109*758e9fbaSOystein Eftevaag free(mycontext);
110*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_GENERAL_FAILURE;
111*758e9fbaSOystein Eftevaag }
112*758e9fbaSOystein Eftevaag mycontext->hash.hash_len = hash_len;
113*758e9fbaSOystein Eftevaag
114*758e9fbaSOystein Eftevaag gcry_error_t r = gcry_md_open(&mycontext->hash.gcry_context,
115*758e9fbaSOystein Eftevaag mycontext->hash.gcry_hash_alg, 0);
116*758e9fbaSOystein Eftevaag if (r != 0) {
117*758e9fbaSOystein Eftevaag LOG_ERROR("GCry error.");
118*758e9fbaSOystein Eftevaag free(mycontext);
119*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_GENERAL_FAILURE;
120*758e9fbaSOystein Eftevaag }
121*758e9fbaSOystein Eftevaag
122*758e9fbaSOystein Eftevaag *context = (IESYS_CRYPTO_CONTEXT_BLOB *) mycontext;
123*758e9fbaSOystein Eftevaag
124*758e9fbaSOystein Eftevaag return TSS2_RC_SUCCESS;
125*758e9fbaSOystein Eftevaag }
126*758e9fbaSOystein Eftevaag
127*758e9fbaSOystein Eftevaag /** Update the digest value of a digest object from a byte buffer.
128*758e9fbaSOystein Eftevaag *
129*758e9fbaSOystein Eftevaag * The context of a digest object will be updated according to the hash
130*758e9fbaSOystein Eftevaag * algorithm of the context.
131*758e9fbaSOystein Eftevaag * @param[in,out] context The context of the digest object which will be updated.
132*758e9fbaSOystein Eftevaag * @param[in] buffer The data for the update.
133*758e9fbaSOystein Eftevaag * @param[in] size The size of the data buffer.
134*758e9fbaSOystein Eftevaag * @retval TSS2_RC_SUCCESS on success.
135*758e9fbaSOystein Eftevaag * @retval TSS2_ESYS_RC_BAD_REFERENCE for invalid parameters.
136*758e9fbaSOystein Eftevaag */
137*758e9fbaSOystein Eftevaag TSS2_RC
iesys_cryptogcry_hash_update(IESYS_CRYPTO_CONTEXT_BLOB * context,const uint8_t * buffer,size_t size)138*758e9fbaSOystein Eftevaag iesys_cryptogcry_hash_update(IESYS_CRYPTO_CONTEXT_BLOB * context,
139*758e9fbaSOystein Eftevaag const uint8_t * buffer, size_t size)
140*758e9fbaSOystein Eftevaag {
141*758e9fbaSOystein Eftevaag LOG_TRACE("called for context %p, buffer %p and size %zd", context, buffer,
142*758e9fbaSOystein Eftevaag size);
143*758e9fbaSOystein Eftevaag if (context == NULL || buffer == NULL) {
144*758e9fbaSOystein Eftevaag LOG_ERROR("Null-Pointer passed");
145*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_BAD_REFERENCE;
146*758e9fbaSOystein Eftevaag }
147*758e9fbaSOystein Eftevaag IESYS_CRYPTOGCRY_CONTEXT *mycontext = (IESYS_CRYPTOGCRY_CONTEXT *) context;
148*758e9fbaSOystein Eftevaag if (mycontext->type != IESYS_CRYPTOGCRY_TYPE_HASH) {
149*758e9fbaSOystein Eftevaag LOG_ERROR("bad context");
150*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_BAD_REFERENCE;
151*758e9fbaSOystein Eftevaag }
152*758e9fbaSOystein Eftevaag
153*758e9fbaSOystein Eftevaag LOGBLOB_TRACE(buffer, size, "Updating hash with");
154*758e9fbaSOystein Eftevaag
155*758e9fbaSOystein Eftevaag gcry_md_write(mycontext->hash.gcry_context, buffer, size);
156*758e9fbaSOystein Eftevaag
157*758e9fbaSOystein Eftevaag return TSS2_RC_SUCCESS;
158*758e9fbaSOystein Eftevaag }
159*758e9fbaSOystein Eftevaag
160*758e9fbaSOystein Eftevaag /** Update the digest value of a digest object from a TPM2B object.
161*758e9fbaSOystein Eftevaag *
162*758e9fbaSOystein Eftevaag * The context of a digest object will be updated according to the hash
163*758e9fbaSOystein Eftevaag * algorithm of the context.
164*758e9fbaSOystein Eftevaag * @param[in,out] context The context of the digest object which will be updated.
165*758e9fbaSOystein Eftevaag * @param[in] b The TPM2B object for the update.
166*758e9fbaSOystein Eftevaag * @retval TSS2_RC_SUCCESS on success.
167*758e9fbaSOystein Eftevaag * @retval TSS2_ESYS_RC_BAD_REFERENCE for invalid parameters.
168*758e9fbaSOystein Eftevaag */
169*758e9fbaSOystein Eftevaag TSS2_RC
iesys_cryptogcry_hash_update2b(IESYS_CRYPTO_CONTEXT_BLOB * context,TPM2B * b)170*758e9fbaSOystein Eftevaag iesys_cryptogcry_hash_update2b(IESYS_CRYPTO_CONTEXT_BLOB * context, TPM2B * b)
171*758e9fbaSOystein Eftevaag {
172*758e9fbaSOystein Eftevaag LOG_TRACE("called for context-pointer %p and 2b-pointer %p", context, b);
173*758e9fbaSOystein Eftevaag if (context == NULL || b == NULL) {
174*758e9fbaSOystein Eftevaag LOG_ERROR("Null-Pointer passed");
175*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_BAD_REFERENCE;
176*758e9fbaSOystein Eftevaag }
177*758e9fbaSOystein Eftevaag TSS2_RC ret = iesys_cryptogcry_hash_update(context, &b->buffer[0], b->size);
178*758e9fbaSOystein Eftevaag return ret;
179*758e9fbaSOystein Eftevaag }
180*758e9fbaSOystein Eftevaag
181*758e9fbaSOystein Eftevaag /** Get the digest value of a digest object and close the context.
182*758e9fbaSOystein Eftevaag *
183*758e9fbaSOystein Eftevaag * The digest value will written to a passed buffer and the resources of the
184*758e9fbaSOystein Eftevaag * digest object are released.
185*758e9fbaSOystein Eftevaag * @param[in,out] context The context of the digest object to be released
186*758e9fbaSOystein Eftevaag * @param[out] buffer The buffer for the digest value (caller-allocated).
187*758e9fbaSOystein Eftevaag * @param[out] size The size of the digest.
188*758e9fbaSOystein Eftevaag * @retval TSS2_RC_SUCCESS on success.
189*758e9fbaSOystein Eftevaag * @retval TSS2_ESYS_RC_BAD_REFERENCE for invalid parameters.
190*758e9fbaSOystein Eftevaag * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
191*758e9fbaSOystein Eftevaag */
192*758e9fbaSOystein Eftevaag TSS2_RC
iesys_cryptogcry_hash_finish(IESYS_CRYPTO_CONTEXT_BLOB ** context,uint8_t * buffer,size_t * size)193*758e9fbaSOystein Eftevaag iesys_cryptogcry_hash_finish(IESYS_CRYPTO_CONTEXT_BLOB ** context,
194*758e9fbaSOystein Eftevaag uint8_t * buffer, size_t * size)
195*758e9fbaSOystein Eftevaag {
196*758e9fbaSOystein Eftevaag LOG_TRACE("called for context-pointer %p, buffer %p and size-pointer %p",
197*758e9fbaSOystein Eftevaag context, buffer, size);
198*758e9fbaSOystein Eftevaag if (context == NULL || *context == NULL || buffer == NULL || size == NULL) {
199*758e9fbaSOystein Eftevaag LOG_ERROR("Null-Pointer passed");
200*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_BAD_REFERENCE;
201*758e9fbaSOystein Eftevaag }
202*758e9fbaSOystein Eftevaag IESYS_CRYPTOGCRY_CONTEXT *mycontext = * context;
203*758e9fbaSOystein Eftevaag if (mycontext->type != IESYS_CRYPTOGCRY_TYPE_HASH) {
204*758e9fbaSOystein Eftevaag LOG_ERROR("bad context");
205*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_BAD_REFERENCE;
206*758e9fbaSOystein Eftevaag }
207*758e9fbaSOystein Eftevaag
208*758e9fbaSOystein Eftevaag if (*size < mycontext->hash.hash_len) {
209*758e9fbaSOystein Eftevaag LOG_ERROR("Buffer too small");
210*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_BAD_SIZE;
211*758e9fbaSOystein Eftevaag }
212*758e9fbaSOystein Eftevaag
213*758e9fbaSOystein Eftevaag uint8_t *cpHash = gcry_md_read(mycontext->hash.gcry_context,
214*758e9fbaSOystein Eftevaag mycontext->hash.gcry_hash_alg);
215*758e9fbaSOystein Eftevaag return_if_null(cpHash, "GCry error.", TSS2_ESYS_RC_GENERAL_FAILURE);
216*758e9fbaSOystein Eftevaag
217*758e9fbaSOystein Eftevaag LOGBLOB_TRACE(cpHash, mycontext->hash.hash_len, "read hash result");
218*758e9fbaSOystein Eftevaag
219*758e9fbaSOystein Eftevaag *size = mycontext->hash.hash_len;
220*758e9fbaSOystein Eftevaag memmove(buffer, cpHash, *size);
221*758e9fbaSOystein Eftevaag
222*758e9fbaSOystein Eftevaag gcry_md_close(mycontext->hash.gcry_context);
223*758e9fbaSOystein Eftevaag
224*758e9fbaSOystein Eftevaag free(mycontext);
225*758e9fbaSOystein Eftevaag *context = NULL;
226*758e9fbaSOystein Eftevaag
227*758e9fbaSOystein Eftevaag return TSS2_RC_SUCCESS;
228*758e9fbaSOystein Eftevaag }
229*758e9fbaSOystein Eftevaag
230*758e9fbaSOystein Eftevaag /** Release the resources of a digest object.
231*758e9fbaSOystein Eftevaag *
232*758e9fbaSOystein Eftevaag * The assigned resources will be released and the context will be set to NULL.
233*758e9fbaSOystein Eftevaag * @param[in,out] context The context of the digest object.
234*758e9fbaSOystein Eftevaag */
235*758e9fbaSOystein Eftevaag void
iesys_cryptogcry_hash_abort(IESYS_CRYPTO_CONTEXT_BLOB ** context)236*758e9fbaSOystein Eftevaag iesys_cryptogcry_hash_abort(IESYS_CRYPTO_CONTEXT_BLOB ** context)
237*758e9fbaSOystein Eftevaag {
238*758e9fbaSOystein Eftevaag LOG_TRACE("called for context-pointer %p", context);
239*758e9fbaSOystein Eftevaag if (context == NULL || *context == NULL) {
240*758e9fbaSOystein Eftevaag LOG_DEBUG("Null-Pointer passed");
241*758e9fbaSOystein Eftevaag return;
242*758e9fbaSOystein Eftevaag }
243*758e9fbaSOystein Eftevaag IESYS_CRYPTOGCRY_CONTEXT *mycontext =
244*758e9fbaSOystein Eftevaag (IESYS_CRYPTOGCRY_CONTEXT *) * context;
245*758e9fbaSOystein Eftevaag if (mycontext->type != IESYS_CRYPTOGCRY_TYPE_HASH) {
246*758e9fbaSOystein Eftevaag LOG_DEBUG("bad context");
247*758e9fbaSOystein Eftevaag return;
248*758e9fbaSOystein Eftevaag }
249*758e9fbaSOystein Eftevaag
250*758e9fbaSOystein Eftevaag gcry_md_close(mycontext->hash.gcry_context);
251*758e9fbaSOystein Eftevaag free(mycontext);
252*758e9fbaSOystein Eftevaag *context = NULL;
253*758e9fbaSOystein Eftevaag }
254*758e9fbaSOystein Eftevaag
255*758e9fbaSOystein Eftevaag /* HMAC */
256*758e9fbaSOystein Eftevaag
257*758e9fbaSOystein Eftevaag /** Provide the context an HMAC digest object from a byte buffer key.
258*758e9fbaSOystein Eftevaag *
259*758e9fbaSOystein Eftevaag * The context will be created and initialized according to the hash function
260*758e9fbaSOystein Eftevaag * and the used HMAC key.
261*758e9fbaSOystein Eftevaag * @param[out] context The created context (callee-allocated).
262*758e9fbaSOystein Eftevaag * @param[in] hmacAlg The hash algorithm for the HMAC computation.
263*758e9fbaSOystein Eftevaag * @param[in] key The byte buffer of the HMAC key.
264*758e9fbaSOystein Eftevaag * @param[in] size The size of the HMAC key.
265*758e9fbaSOystein Eftevaag * @retval TSS2_RC_SUCCESS on success.
266*758e9fbaSOystein Eftevaag * @retval TSS2_ESYS_RC_BAD_REFERENCE for invalid parameters.
267*758e9fbaSOystein Eftevaag * @retval TSS2_ESYS_RC_MEMORY Memory cannot be allocated.
268*758e9fbaSOystein Eftevaag * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
269*758e9fbaSOystein Eftevaag */
270*758e9fbaSOystein Eftevaag TSS2_RC
iesys_cryptogcry_hmac_start(IESYS_CRYPTO_CONTEXT_BLOB ** context,TPM2_ALG_ID hmacAlg,const uint8_t * key,size_t size)271*758e9fbaSOystein Eftevaag iesys_cryptogcry_hmac_start(IESYS_CRYPTO_CONTEXT_BLOB ** context,
272*758e9fbaSOystein Eftevaag TPM2_ALG_ID hmacAlg,
273*758e9fbaSOystein Eftevaag const uint8_t * key, size_t size)
274*758e9fbaSOystein Eftevaag {
275*758e9fbaSOystein Eftevaag TSS2_RC r;
276*758e9fbaSOystein Eftevaag
277*758e9fbaSOystein Eftevaag LOG_TRACE("called for context-pointer %p and hmacAlg %d", context, hmacAlg);
278*758e9fbaSOystein Eftevaag LOGBLOB_TRACE(key, size, "Starting hmac with");
279*758e9fbaSOystein Eftevaag if (context == NULL || key == NULL) {
280*758e9fbaSOystein Eftevaag LOG_ERROR("Null-Pointer passed in for context");
281*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_BAD_REFERENCE;
282*758e9fbaSOystein Eftevaag }
283*758e9fbaSOystein Eftevaag IESYS_CRYPTOGCRY_CONTEXT *mycontext =
284*758e9fbaSOystein Eftevaag calloc(1, sizeof(IESYS_CRYPTOGCRY_CONTEXT));
285*758e9fbaSOystein Eftevaag return_if_null(mycontext, "Out of Memory", TSS2_ESYS_RC_MEMORY);
286*758e9fbaSOystein Eftevaag
287*758e9fbaSOystein Eftevaag switch (hmacAlg) {
288*758e9fbaSOystein Eftevaag case TPM2_ALG_SHA1:
289*758e9fbaSOystein Eftevaag mycontext->hmac.gcry_hmac_alg = GCRY_MAC_HMAC_SHA1;
290*758e9fbaSOystein Eftevaag break;
291*758e9fbaSOystein Eftevaag case TPM2_ALG_SHA256:
292*758e9fbaSOystein Eftevaag mycontext->hmac.gcry_hmac_alg = GCRY_MAC_HMAC_SHA256;
293*758e9fbaSOystein Eftevaag break;
294*758e9fbaSOystein Eftevaag default:
295*758e9fbaSOystein Eftevaag LOG_ERROR("Unsupported hmac algo.");
296*758e9fbaSOystein Eftevaag free(mycontext);
297*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_NOT_IMPLEMENTED;
298*758e9fbaSOystein Eftevaag }
299*758e9fbaSOystein Eftevaag
300*758e9fbaSOystein Eftevaag int hmac_len = gcry_mac_get_algo_maclen(mycontext->hmac.gcry_hmac_alg);
301*758e9fbaSOystein Eftevaag if (hmac_len <= 0) {
302*758e9fbaSOystein Eftevaag LOG_ERROR("GCry error.");
303*758e9fbaSOystein Eftevaag free(mycontext);
304*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_GENERAL_FAILURE;
305*758e9fbaSOystein Eftevaag }
306*758e9fbaSOystein Eftevaag
307*758e9fbaSOystein Eftevaag mycontext->type = IESYS_CRYPTOGCRY_TYPE_HMAC;
308*758e9fbaSOystein Eftevaag mycontext->hmac.hmac_len = hmac_len;
309*758e9fbaSOystein Eftevaag
310*758e9fbaSOystein Eftevaag r = gcry_mac_open(&mycontext->hmac.gcry_context,
311*758e9fbaSOystein Eftevaag mycontext->hmac.gcry_hmac_alg, 0, NULL);
312*758e9fbaSOystein Eftevaag if (r != 0) {
313*758e9fbaSOystein Eftevaag LOG_ERROR("GCry error.");
314*758e9fbaSOystein Eftevaag free(mycontext);
315*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_GENERAL_FAILURE;
316*758e9fbaSOystein Eftevaag }
317*758e9fbaSOystein Eftevaag
318*758e9fbaSOystein Eftevaag r = gcry_mac_setkey(mycontext->hmac.gcry_context, key, size);
319*758e9fbaSOystein Eftevaag if (r != 0) {
320*758e9fbaSOystein Eftevaag LOG_ERROR("GCry error.");
321*758e9fbaSOystein Eftevaag gcry_mac_close(mycontext->hmac.gcry_context);
322*758e9fbaSOystein Eftevaag free(mycontext);
323*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_GENERAL_FAILURE;
324*758e9fbaSOystein Eftevaag }
325*758e9fbaSOystein Eftevaag
326*758e9fbaSOystein Eftevaag *context = (IESYS_CRYPTO_CONTEXT_BLOB *) mycontext;
327*758e9fbaSOystein Eftevaag
328*758e9fbaSOystein Eftevaag return TSS2_RC_SUCCESS;
329*758e9fbaSOystein Eftevaag }
330*758e9fbaSOystein Eftevaag
331*758e9fbaSOystein Eftevaag /** Update and HMAC digest value from a byte buffer.
332*758e9fbaSOystein Eftevaag *
333*758e9fbaSOystein Eftevaag * The context of a digest object will be updated according to the hash
334*758e9fbaSOystein Eftevaag * algorithm and the key of the context.
335*758e9fbaSOystein Eftevaag * @param[in,out] context The context of the digest object which will be updated.
336*758e9fbaSOystein Eftevaag * @param[in] buffer The data for the update.
337*758e9fbaSOystein Eftevaag * @param[in] size The size of the data buffer.
338*758e9fbaSOystein Eftevaag * @retval TSS2_RC_SUCCESS on success.
339*758e9fbaSOystein Eftevaag * @retval TSS2_ESYS_RC_BAD_REFERENCE for invalid parameters.
340*758e9fbaSOystein Eftevaag */
341*758e9fbaSOystein Eftevaag TSS2_RC
iesys_cryptogcry_hmac_update(IESYS_CRYPTO_CONTEXT_BLOB * context,const uint8_t * buffer,size_t size)342*758e9fbaSOystein Eftevaag iesys_cryptogcry_hmac_update(IESYS_CRYPTO_CONTEXT_BLOB * context,
343*758e9fbaSOystein Eftevaag const uint8_t * buffer, size_t size)
344*758e9fbaSOystein Eftevaag {
345*758e9fbaSOystein Eftevaag LOG_TRACE("called for context %p, buffer %p and size %zd",
346*758e9fbaSOystein Eftevaag context, buffer, size);
347*758e9fbaSOystein Eftevaag if (context == NULL || buffer == NULL) {
348*758e9fbaSOystein Eftevaag LOG_ERROR("Null-Pointer passed");
349*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_BAD_REFERENCE;
350*758e9fbaSOystein Eftevaag }
351*758e9fbaSOystein Eftevaag IESYS_CRYPTOGCRY_CONTEXT *mycontext = (IESYS_CRYPTOGCRY_CONTEXT *) context;
352*758e9fbaSOystein Eftevaag if (mycontext->type != IESYS_CRYPTOGCRY_TYPE_HMAC) {
353*758e9fbaSOystein Eftevaag LOG_ERROR("bad context");
354*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_BAD_REFERENCE;
355*758e9fbaSOystein Eftevaag }
356*758e9fbaSOystein Eftevaag
357*758e9fbaSOystein Eftevaag LOGBLOB_TRACE(buffer, size, "Updating hmac with");
358*758e9fbaSOystein Eftevaag
359*758e9fbaSOystein Eftevaag if (GPG_ERR_NO_ERROR != gcry_mac_write(mycontext->hmac.gcry_context, buffer, size)) {
360*758e9fbaSOystein Eftevaag return_error(TSS2_ESYS_RC_GENERAL_FAILURE, "Gcrypt hmac update");
361*758e9fbaSOystein Eftevaag }
362*758e9fbaSOystein Eftevaag
363*758e9fbaSOystein Eftevaag return TSS2_RC_SUCCESS;
364*758e9fbaSOystein Eftevaag }
365*758e9fbaSOystein Eftevaag
366*758e9fbaSOystein Eftevaag /** Update and HMAC digest value from a TPM2B object.
367*758e9fbaSOystein Eftevaag *
368*758e9fbaSOystein Eftevaag * The context of a digest object will be updated according to the hash
369*758e9fbaSOystein Eftevaag * algorithm and the key of the context.
370*758e9fbaSOystein Eftevaag * @param[in,out] context The context of the digest object which will be updated.
371*758e9fbaSOystein Eftevaag * @param[in] b The TPM2B object for the update.
372*758e9fbaSOystein Eftevaag * @retval TSS2_RC_SUCCESS on success.
373*758e9fbaSOystein Eftevaag * @retval TSS2_ESYS_RC_BAD_REFERENCE for invalid parameters.
374*758e9fbaSOystein Eftevaag */
375*758e9fbaSOystein Eftevaag TSS2_RC
iesys_cryptogcry_hmac_update2b(IESYS_CRYPTO_CONTEXT_BLOB * context,TPM2B * b)376*758e9fbaSOystein Eftevaag iesys_cryptogcry_hmac_update2b(IESYS_CRYPTO_CONTEXT_BLOB * context, TPM2B * b)
377*758e9fbaSOystein Eftevaag {
378*758e9fbaSOystein Eftevaag LOG_TRACE("called for context-pointer %p and 2b-pointer %p", context, b);
379*758e9fbaSOystein Eftevaag if (context == NULL || b == NULL) {
380*758e9fbaSOystein Eftevaag LOG_ERROR("Null-Pointer passed");
381*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_BAD_REFERENCE;
382*758e9fbaSOystein Eftevaag }
383*758e9fbaSOystein Eftevaag TSS2_RC ret = iesys_cryptogcry_hmac_update(context, &b->buffer[0], b->size);
384*758e9fbaSOystein Eftevaag return ret;
385*758e9fbaSOystein Eftevaag }
386*758e9fbaSOystein Eftevaag
387*758e9fbaSOystein Eftevaag /** Write the HMAC digest value to a byte buffer and close the context.
388*758e9fbaSOystein Eftevaag *
389*758e9fbaSOystein Eftevaag * The digest value will written to a passed buffer and the resources of the
390*758e9fbaSOystein Eftevaag * HMAC object are released.
391*758e9fbaSOystein Eftevaag * @param[in,out] context The context of the HMAC object.
392*758e9fbaSOystein Eftevaag * @param[out] buffer The buffer for the digest value (caller-allocated).
393*758e9fbaSOystein Eftevaag * @param[out] size The size of the digest.
394*758e9fbaSOystein Eftevaag * @retval TSS2_RC_SUCCESS on success.
395*758e9fbaSOystein Eftevaag * @retval TSS2_ESYS_RC_BAD_REFERENCE for invalid parameters.
396*758e9fbaSOystein Eftevaag * @retval TSS2_ESYS_RC_BAD_SIZE If the size passed is lower than the HMAC length.
397*758e9fbaSOystein Eftevaag * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
398*758e9fbaSOystein Eftevaag */
399*758e9fbaSOystein Eftevaag TSS2_RC
iesys_cryptogcry_hmac_finish(IESYS_CRYPTO_CONTEXT_BLOB ** context,uint8_t * buffer,size_t * size)400*758e9fbaSOystein Eftevaag iesys_cryptogcry_hmac_finish(IESYS_CRYPTO_CONTEXT_BLOB ** context,
401*758e9fbaSOystein Eftevaag uint8_t * buffer, size_t * size)
402*758e9fbaSOystein Eftevaag {
403*758e9fbaSOystein Eftevaag LOG_TRACE("called for context-pointer %p, buffer %p and size-pointer %p",
404*758e9fbaSOystein Eftevaag context, buffer, size);
405*758e9fbaSOystein Eftevaag if (context == NULL || *context == NULL || buffer == NULL || size == NULL) {
406*758e9fbaSOystein Eftevaag LOG_ERROR("Null-Pointer passed");
407*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_BAD_REFERENCE;
408*758e9fbaSOystein Eftevaag }
409*758e9fbaSOystein Eftevaag IESYS_CRYPTOGCRY_CONTEXT *mycontext =
410*758e9fbaSOystein Eftevaag (IESYS_CRYPTOGCRY_CONTEXT *) * context;
411*758e9fbaSOystein Eftevaag if (mycontext->type != IESYS_CRYPTOGCRY_TYPE_HMAC) {
412*758e9fbaSOystein Eftevaag LOG_ERROR("bad context");
413*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_BAD_REFERENCE;
414*758e9fbaSOystein Eftevaag }
415*758e9fbaSOystein Eftevaag
416*758e9fbaSOystein Eftevaag if (*size < mycontext->hmac.hmac_len) {
417*758e9fbaSOystein Eftevaag LOG_ERROR("Buffer too small");
418*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_BAD_SIZE;
419*758e9fbaSOystein Eftevaag }
420*758e9fbaSOystein Eftevaag
421*758e9fbaSOystein Eftevaag TSS2_RC r = gcry_mac_read(mycontext->hmac.gcry_context, buffer, size);
422*758e9fbaSOystein Eftevaag if (r != 0) {
423*758e9fbaSOystein Eftevaag LOG_ERROR("GCry error.");
424*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_GENERAL_FAILURE;
425*758e9fbaSOystein Eftevaag }
426*758e9fbaSOystein Eftevaag
427*758e9fbaSOystein Eftevaag LOGBLOB_TRACE(buffer, *size, "read hmac result");
428*758e9fbaSOystein Eftevaag
429*758e9fbaSOystein Eftevaag gcry_mac_close(mycontext->hmac.gcry_context);
430*758e9fbaSOystein Eftevaag
431*758e9fbaSOystein Eftevaag free(mycontext);
432*758e9fbaSOystein Eftevaag *context = NULL;
433*758e9fbaSOystein Eftevaag
434*758e9fbaSOystein Eftevaag return TSS2_RC_SUCCESS;
435*758e9fbaSOystein Eftevaag }
436*758e9fbaSOystein Eftevaag
437*758e9fbaSOystein Eftevaag /** Write the HMAC digest value to a TPM2B object and close the context.
438*758e9fbaSOystein Eftevaag *
439*758e9fbaSOystein Eftevaag * The digest value will written to a passed TPM2B object and the resources of
440*758e9fbaSOystein Eftevaag * the HMAC object are released.
441*758e9fbaSOystein Eftevaag * @param[in,out] context The context of the HMAC object.
442*758e9fbaSOystein Eftevaag * @param[out] hmac The buffer for the digest value (caller-allocated).
443*758e9fbaSOystein Eftevaag * @retval TSS2_RC_SUCCESS on success.
444*758e9fbaSOystein Eftevaag * @retval TSS2_ESYS_RC_BAD_REFERENCE for invalid parameters.
445*758e9fbaSOystein Eftevaag * @retval TSS2_ESYS_RC_BAD_SIZE if the size passed is lower than the HMAC length.
446*758e9fbaSOystein Eftevaag * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
447*758e9fbaSOystein Eftevaag */
448*758e9fbaSOystein Eftevaag TSS2_RC
iesys_cryptogcry_hmac_finish2b(IESYS_CRYPTO_CONTEXT_BLOB ** context,TPM2B * hmac)449*758e9fbaSOystein Eftevaag iesys_cryptogcry_hmac_finish2b(IESYS_CRYPTO_CONTEXT_BLOB ** context, TPM2B * hmac)
450*758e9fbaSOystein Eftevaag {
451*758e9fbaSOystein Eftevaag LOG_TRACE("called for context-pointer %p and 2b-pointer %p", context, hmac);
452*758e9fbaSOystein Eftevaag if (context == NULL || *context == NULL || hmac == NULL) {
453*758e9fbaSOystein Eftevaag LOG_ERROR("Null-Pointer passed");
454*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_BAD_REFERENCE;
455*758e9fbaSOystein Eftevaag }
456*758e9fbaSOystein Eftevaag size_t s = hmac->size;
457*758e9fbaSOystein Eftevaag TSS2_RC ret = iesys_cryptogcry_hmac_finish(context, &hmac->buffer[0], &s);
458*758e9fbaSOystein Eftevaag hmac->size = s;
459*758e9fbaSOystein Eftevaag return ret;
460*758e9fbaSOystein Eftevaag }
461*758e9fbaSOystein Eftevaag
462*758e9fbaSOystein Eftevaag /** Release the resources of an HAMC object.
463*758e9fbaSOystein Eftevaag *
464*758e9fbaSOystein Eftevaag * The assigned resources will be released and the context will be set to NULL.
465*758e9fbaSOystein Eftevaag * @param[in,out] context The context of the HMAC object.
466*758e9fbaSOystein Eftevaag */
467*758e9fbaSOystein Eftevaag void
iesys_cryptogcry_hmac_abort(IESYS_CRYPTO_CONTEXT_BLOB ** context)468*758e9fbaSOystein Eftevaag iesys_cryptogcry_hmac_abort(IESYS_CRYPTO_CONTEXT_BLOB ** context)
469*758e9fbaSOystein Eftevaag {
470*758e9fbaSOystein Eftevaag LOG_TRACE("called for context-pointer %p", context);
471*758e9fbaSOystein Eftevaag if (context == NULL || *context == NULL) {
472*758e9fbaSOystein Eftevaag LOG_DEBUG("Null-Pointer passed");
473*758e9fbaSOystein Eftevaag return;
474*758e9fbaSOystein Eftevaag }
475*758e9fbaSOystein Eftevaag if (*context != NULL) {
476*758e9fbaSOystein Eftevaag IESYS_CRYPTOGCRY_CONTEXT *mycontext =
477*758e9fbaSOystein Eftevaag (IESYS_CRYPTOGCRY_CONTEXT *) * context;
478*758e9fbaSOystein Eftevaag if (mycontext->type != IESYS_CRYPTOGCRY_TYPE_HMAC) {
479*758e9fbaSOystein Eftevaag LOG_DEBUG("bad context");
480*758e9fbaSOystein Eftevaag return;
481*758e9fbaSOystein Eftevaag }
482*758e9fbaSOystein Eftevaag
483*758e9fbaSOystein Eftevaag gcry_mac_close(mycontext->hmac.gcry_context);
484*758e9fbaSOystein Eftevaag
485*758e9fbaSOystein Eftevaag free(mycontext);
486*758e9fbaSOystein Eftevaag *context = NULL;
487*758e9fbaSOystein Eftevaag }
488*758e9fbaSOystein Eftevaag }
489*758e9fbaSOystein Eftevaag
490*758e9fbaSOystein Eftevaag /** Compute random TPM2B data.
491*758e9fbaSOystein Eftevaag *
492*758e9fbaSOystein Eftevaag * The random data will be generated and written to a passed TPM2B structure.
493*758e9fbaSOystein Eftevaag * @param[out] nonce The TPM2B structure for the random data (caller-allocated).
494*758e9fbaSOystein Eftevaag * @param[in] num_bytes The number of bytes to be generated.
495*758e9fbaSOystein Eftevaag * @retval TSS2_RC_SUCCESS on success.
496*758e9fbaSOystein Eftevaag */
497*758e9fbaSOystein Eftevaag TSS2_RC
iesys_cryptogcry_random2b(TPM2B_NONCE * nonce,size_t num_bytes)498*758e9fbaSOystein Eftevaag iesys_cryptogcry_random2b(TPM2B_NONCE * nonce, size_t num_bytes)
499*758e9fbaSOystein Eftevaag {
500*758e9fbaSOystein Eftevaag if (num_bytes == 0) {
501*758e9fbaSOystein Eftevaag nonce->size = sizeof(TPMU_HA);
502*758e9fbaSOystein Eftevaag } else {
503*758e9fbaSOystein Eftevaag nonce->size = num_bytes;
504*758e9fbaSOystein Eftevaag }
505*758e9fbaSOystein Eftevaag /*
506*758e9fbaSOystein Eftevaag * possible values for random level:
507*758e9fbaSOystein Eftevaag * GCRY_WEAK_RANDOM GCRY_STRONG_RANDOM GCRY_VERY_STRONG_RANDOM
508*758e9fbaSOystein Eftevaag */
509*758e9fbaSOystein Eftevaag gcry_randomize(&nonce->buffer[0], nonce->size, GCRY_STRONG_RANDOM);
510*758e9fbaSOystein Eftevaag return TSS2_RC_SUCCESS;
511*758e9fbaSOystein Eftevaag }
512*758e9fbaSOystein Eftevaag
513*758e9fbaSOystein Eftevaag /** Encryption of a buffer using a public (RSA) key.
514*758e9fbaSOystein Eftevaag *
515*758e9fbaSOystein Eftevaag * Encrypting a buffer using a public key is used for example during
516*758e9fbaSOystein Eftevaag * Esys_StartAuthSession in order to encrypt the salt value.
517*758e9fbaSOystein Eftevaag * @param[in] key The key to be used for encryption.
518*758e9fbaSOystein Eftevaag * @param[in] in_size The size of the buffer to be encrypted.
519*758e9fbaSOystein Eftevaag * @param[in] in_buffer The data buffer to be encrypted.
520*758e9fbaSOystein Eftevaag * @param[in] max_out_size The maximum size for the output encrypted buffer.
521*758e9fbaSOystein Eftevaag * @param[out] out_buffer The encrypted buffer.
522*758e9fbaSOystein Eftevaag * @param[out] out_size The size of the encrypted output.
523*758e9fbaSOystein Eftevaag * @param[in] label The label used in the encryption scheme.
524*758e9fbaSOystein Eftevaag * @retval TSS2_RC_SUCCESS on success
525*758e9fbaSOystein Eftevaag * @retval TSS2_ESYS_RC_BAD_VALUE The algorithm of key is not implemented.
526*758e9fbaSOystein Eftevaag * @retval TSS2_ESYS_RC_GENERAL_FAILURE The internal crypto engine failed.
527*758e9fbaSOystein Eftevaag */
528*758e9fbaSOystein Eftevaag TSS2_RC
iesys_cryptogcry_pk_encrypt(TPM2B_PUBLIC * key,size_t in_size,BYTE * in_buffer,size_t max_out_size,BYTE * out_buffer,size_t * out_size,const char * label)529*758e9fbaSOystein Eftevaag iesys_cryptogcry_pk_encrypt(TPM2B_PUBLIC * key,
530*758e9fbaSOystein Eftevaag size_t in_size,
531*758e9fbaSOystein Eftevaag BYTE * in_buffer,
532*758e9fbaSOystein Eftevaag size_t max_out_size,
533*758e9fbaSOystein Eftevaag BYTE * out_buffer,
534*758e9fbaSOystein Eftevaag size_t * out_size, const char *label)
535*758e9fbaSOystein Eftevaag {
536*758e9fbaSOystein Eftevaag TSS2_RC r;
537*758e9fbaSOystein Eftevaag gcry_error_t err;
538*758e9fbaSOystein Eftevaag char *hash_alg;
539*758e9fbaSOystein Eftevaag size_t lsize = 0;
540*758e9fbaSOystein Eftevaag BYTE exponent[4] = { 0x00, 0x01, 0x00, 0x01 };
541*758e9fbaSOystein Eftevaag char *padding;
542*758e9fbaSOystein Eftevaag gcry_sexp_t sexp_data = NULL, sexp_key = NULL,
543*758e9fbaSOystein Eftevaag sexp_cipher = NULL, sexp_cipher_a = NULL;
544*758e9fbaSOystein Eftevaag gcry_mpi_t mpi_cipher = NULL;
545*758e9fbaSOystein Eftevaag
546*758e9fbaSOystein Eftevaag if (label != NULL)
547*758e9fbaSOystein Eftevaag lsize = strlen(label) + 1;
548*758e9fbaSOystein Eftevaag switch (key->publicArea.nameAlg) {
549*758e9fbaSOystein Eftevaag case TPM2_ALG_SHA1:
550*758e9fbaSOystein Eftevaag hash_alg = "sha1";
551*758e9fbaSOystein Eftevaag break;
552*758e9fbaSOystein Eftevaag case TPM2_ALG_SHA256:
553*758e9fbaSOystein Eftevaag hash_alg = "sha256";
554*758e9fbaSOystein Eftevaag break;
555*758e9fbaSOystein Eftevaag default:
556*758e9fbaSOystein Eftevaag LOG_ERROR("Hash alg not implemented");
557*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_NOT_IMPLEMENTED;
558*758e9fbaSOystein Eftevaag }
559*758e9fbaSOystein Eftevaag switch (key->publicArea.parameters.rsaDetail.scheme.scheme) {
560*758e9fbaSOystein Eftevaag case TPM2_ALG_NULL:
561*758e9fbaSOystein Eftevaag padding = "raw";
562*758e9fbaSOystein Eftevaag break;
563*758e9fbaSOystein Eftevaag case TPM2_ALG_RSAES:
564*758e9fbaSOystein Eftevaag padding = "pkcs1";
565*758e9fbaSOystein Eftevaag break;
566*758e9fbaSOystein Eftevaag case TPM2_ALG_OAEP:
567*758e9fbaSOystein Eftevaag padding = "oaep";
568*758e9fbaSOystein Eftevaag break;
569*758e9fbaSOystein Eftevaag default:
570*758e9fbaSOystein Eftevaag LOG_ERROR("Illegal RSA scheme");
571*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_BAD_VALUE;
572*758e9fbaSOystein Eftevaag }
573*758e9fbaSOystein Eftevaag size_t offset = 0;
574*758e9fbaSOystein Eftevaag UINT32 exp;
575*758e9fbaSOystein Eftevaag if (key->publicArea.parameters.rsaDetail.exponent == 0)
576*758e9fbaSOystein Eftevaag exp = 65537;
577*758e9fbaSOystein Eftevaag else
578*758e9fbaSOystein Eftevaag exp = key->publicArea.parameters.rsaDetail.exponent;
579*758e9fbaSOystein Eftevaag r = Tss2_MU_UINT32_Marshal(exp, &exponent[0], sizeof(UINT32), &offset);
580*758e9fbaSOystein Eftevaag if (r != TSS2_RC_SUCCESS) {
581*758e9fbaSOystein Eftevaag LOG_ERROR("Marshaling");
582*758e9fbaSOystein Eftevaag return r;
583*758e9fbaSOystein Eftevaag }
584*758e9fbaSOystein Eftevaag err = gcry_sexp_build(&sexp_data, NULL,
585*758e9fbaSOystein Eftevaag "(data (flags %s) (hash-algo %s) (label %b) (value %b) )",
586*758e9fbaSOystein Eftevaag padding, hash_alg, lsize, label, (int)in_size,
587*758e9fbaSOystein Eftevaag in_buffer);
588*758e9fbaSOystein Eftevaag if (err != GPG_ERR_NO_ERROR) {
589*758e9fbaSOystein Eftevaag LOG_ERROR("Function gcry_sexp_build");
590*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_GENERAL_FAILURE;
591*758e9fbaSOystein Eftevaag }
592*758e9fbaSOystein Eftevaag err = gcry_sexp_build(&sexp_key, NULL, "(public-key (rsa (n %b) (e %b)))",
593*758e9fbaSOystein Eftevaag (int)key->publicArea.unique.rsa.size,
594*758e9fbaSOystein Eftevaag &key->publicArea.unique.rsa.buffer[0], 4, exponent);
595*758e9fbaSOystein Eftevaag if (err != GPG_ERR_NO_ERROR) {
596*758e9fbaSOystein Eftevaag goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
597*758e9fbaSOystein Eftevaag "Function gcry_sexp_build", cleanup);
598*758e9fbaSOystein Eftevaag }
599*758e9fbaSOystein Eftevaag err = gcry_pk_encrypt(&sexp_cipher, sexp_data, sexp_key);
600*758e9fbaSOystein Eftevaag if (err != GPG_ERR_NO_ERROR) {
601*758e9fbaSOystein Eftevaag fprintf (stderr, "Failure: %s/%s\n",
602*758e9fbaSOystein Eftevaag gcry_strsource (err),
603*758e9fbaSOystein Eftevaag gcry_strerror (err));
604*758e9fbaSOystein Eftevaag goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
605*758e9fbaSOystein Eftevaag "Function gcry_pk_encrypt", cleanup);
606*758e9fbaSOystein Eftevaag }
607*758e9fbaSOystein Eftevaag sexp_cipher_a = gcry_sexp_find_token(sexp_cipher, "a", 0);
608*758e9fbaSOystein Eftevaag mpi_cipher = gcry_sexp_nth_mpi(sexp_cipher_a, 1, GCRYMPI_FMT_USG);
609*758e9fbaSOystein Eftevaag if (!mpi_cipher) {
610*758e9fbaSOystein Eftevaag LOG_ERROR("Function gcry_sexp_nth_mpi");
611*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_MEMORY;
612*758e9fbaSOystein Eftevaag }
613*758e9fbaSOystein Eftevaag err = mpi2bin(mpi_cipher, &out_buffer[0], key->publicArea.unique.rsa.size, max_out_size);
614*758e9fbaSOystein Eftevaag if (err != GPG_ERR_NO_ERROR) {
615*758e9fbaSOystein Eftevaag goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
616*758e9fbaSOystein Eftevaag "Function mpi2bin", cleanup);
617*758e9fbaSOystein Eftevaag }
618*758e9fbaSOystein Eftevaag
619*758e9fbaSOystein Eftevaag *out_size = key->publicArea.unique.rsa.size;
620*758e9fbaSOystein Eftevaag gcry_mpi_release(mpi_cipher);
621*758e9fbaSOystein Eftevaag gcry_sexp_release(sexp_data);
622*758e9fbaSOystein Eftevaag gcry_sexp_release(sexp_key);
623*758e9fbaSOystein Eftevaag gcry_sexp_release(sexp_cipher);
624*758e9fbaSOystein Eftevaag gcry_sexp_release(sexp_cipher_a);
625*758e9fbaSOystein Eftevaag return TSS2_RC_SUCCESS;
626*758e9fbaSOystein Eftevaag
627*758e9fbaSOystein Eftevaag cleanup:
628*758e9fbaSOystein Eftevaag if (mpi_cipher)
629*758e9fbaSOystein Eftevaag gcry_mpi_release(mpi_cipher);
630*758e9fbaSOystein Eftevaag
631*758e9fbaSOystein Eftevaag if (mpi_cipher)
632*758e9fbaSOystein Eftevaag gcry_sexp_release(sexp_data);
633*758e9fbaSOystein Eftevaag
634*758e9fbaSOystein Eftevaag if (mpi_cipher)
635*758e9fbaSOystein Eftevaag gcry_sexp_release(sexp_key);
636*758e9fbaSOystein Eftevaag
637*758e9fbaSOystein Eftevaag if (mpi_cipher)
638*758e9fbaSOystein Eftevaag gcry_sexp_release(sexp_cipher);
639*758e9fbaSOystein Eftevaag
640*758e9fbaSOystein Eftevaag if (mpi_cipher)
641*758e9fbaSOystein Eftevaag gcry_sexp_release(sexp_cipher_a);
642*758e9fbaSOystein Eftevaag
643*758e9fbaSOystein Eftevaag return r;
644*758e9fbaSOystein Eftevaag }
645*758e9fbaSOystein Eftevaag
646*758e9fbaSOystein Eftevaag /** Computation of ephemeral ECC key and shared secret Z.
647*758e9fbaSOystein Eftevaag *
648*758e9fbaSOystein Eftevaag * According to the description in TPM spec part 1 C 6.1 a shared secret
649*758e9fbaSOystein Eftevaag * between application and TPM is computed (ECDH). An ephemeral ECC key and a
650*758e9fbaSOystein Eftevaag * TPM keyare used for the ECDH key exchange.
651*758e9fbaSOystein Eftevaag * @param[in] key The key to be used for ECDH key exchange.
652*758e9fbaSOystein Eftevaag * @param[in] max_out_size the max size for the output of the public key of the
653*758e9fbaSOystein Eftevaag * computed ephemeral key.
654*758e9fbaSOystein Eftevaag * @param[out] Z The computed shared secret.
655*758e9fbaSOystein Eftevaag * @param[out] Q The public part of the ephemeral key in TPM format.
656*758e9fbaSOystein Eftevaag * @param[out] out_buffer The public part of the ephemeral key will be marshaled
657*758e9fbaSOystein Eftevaag * to this buffer.
658*758e9fbaSOystein Eftevaag * @param[out] out_size The size of the marshaled output.
659*758e9fbaSOystein Eftevaag * @retval TSS2_RC_SUCCESS on success
660*758e9fbaSOystein Eftevaag * @retval TSS2_ESYS_RC_BAD_VALUE The algorithm of key is not implemented.
661*758e9fbaSOystein Eftevaag * @retval TSS2_ESYS_RC_GENERAL_FAILURE The internal crypto engine failed.
662*758e9fbaSOystein Eftevaag */
663*758e9fbaSOystein Eftevaag TSS2_RC
iesys_cryptogcry_get_ecdh_point(TPM2B_PUBLIC * key,size_t max_out_size,TPM2B_ECC_PARAMETER * Z,TPMS_ECC_POINT * Q,BYTE * out_buffer,size_t * out_size)664*758e9fbaSOystein Eftevaag iesys_cryptogcry_get_ecdh_point(TPM2B_PUBLIC *key,
665*758e9fbaSOystein Eftevaag size_t max_out_size,
666*758e9fbaSOystein Eftevaag TPM2B_ECC_PARAMETER *Z,
667*758e9fbaSOystein Eftevaag TPMS_ECC_POINT *Q,
668*758e9fbaSOystein Eftevaag BYTE * out_buffer,
669*758e9fbaSOystein Eftevaag size_t * out_size)
670*758e9fbaSOystein Eftevaag {
671*758e9fbaSOystein Eftevaag /*
672*758e9fbaSOystein Eftevaag * Format strings for some gcrypt sexps have to be created with sprintf due to
673*758e9fbaSOystein Eftevaag * a bug in libgcrypt. %s does not work in libgcypt with these sexps.
674*758e9fbaSOystein Eftevaag */
675*758e9fbaSOystein Eftevaag #define SEXP_GENKEY_ECC "(genkey (ecc (curve %s)))"
676*758e9fbaSOystein Eftevaag #define SEXP_ECC_POINT "(ecc (curve %s) (q.x %sb) (q.y %sb))"
677*758e9fbaSOystein Eftevaag
678*758e9fbaSOystein Eftevaag TSS2_RC r;
679*758e9fbaSOystein Eftevaag char *curveId;
680*758e9fbaSOystein Eftevaag gcry_sexp_t mpi_tpm_sq = NULL; /* sexp for public part of TPM key*/
681*758e9fbaSOystein Eftevaag gcry_sexp_t mpi_sd = NULL; /* sexp for private part of ephemeral key */
682*758e9fbaSOystein Eftevaag gcry_sexp_t mpi_s_pub_q = NULL; /* sexp for public part of ephemeral key */
683*758e9fbaSOystein Eftevaag gcry_mpi_point_t mpi_q = NULL; /* public point of ephemeral key */
684*758e9fbaSOystein Eftevaag gcry_mpi_point_t mpi_tpm_q = NULL; /* public point of TPM key */
685*758e9fbaSOystein Eftevaag gcry_mpi_t mpi_d = NULL; /* private part of ephemeral key */
686*758e9fbaSOystein Eftevaag gcry_mpi_point_t mpi_qd = NULL; /* result of mpi_tpm_q * mpi_d */
687*758e9fbaSOystein Eftevaag gcry_ctx_t ctx = NULL; /* context for ec curves */
688*758e9fbaSOystein Eftevaag size_t offset = 0;
689*758e9fbaSOystein Eftevaag gcry_mpi_t mpi_x = gcry_mpi_new(521); /* big number for x coordinate */
690*758e9fbaSOystein Eftevaag gcry_mpi_t mpi_y = gcry_mpi_new(521); /* big number for y coordinate */
691*758e9fbaSOystein Eftevaag size_t max_ecc_size; /* max size of ecc coordinate */
692*758e9fbaSOystein Eftevaag
693*758e9fbaSOystein Eftevaag /* Set libcrypt constant for curve type */
694*758e9fbaSOystein Eftevaag switch (key->publicArea.parameters.eccDetail.curveID) {
695*758e9fbaSOystein Eftevaag case TPM2_ECC_NIST_P192:
696*758e9fbaSOystein Eftevaag curveId = "\"NIST P-192\"";
697*758e9fbaSOystein Eftevaag max_ecc_size = (192+7)/8;
698*758e9fbaSOystein Eftevaag break;
699*758e9fbaSOystein Eftevaag case TPM2_ECC_NIST_P224:
700*758e9fbaSOystein Eftevaag curveId = "\"NIST P-224\"";
701*758e9fbaSOystein Eftevaag max_ecc_size = (224+7)/8;
702*758e9fbaSOystein Eftevaag break;
703*758e9fbaSOystein Eftevaag case TPM2_ECC_NIST_P256:
704*758e9fbaSOystein Eftevaag curveId = "\"NIST P-256\"";
705*758e9fbaSOystein Eftevaag max_ecc_size = (256+7)/8;
706*758e9fbaSOystein Eftevaag break;
707*758e9fbaSOystein Eftevaag case TPM2_ECC_NIST_P384:
708*758e9fbaSOystein Eftevaag curveId = "\"NIST P-384\"";
709*758e9fbaSOystein Eftevaag max_ecc_size = (384+7)/8;
710*758e9fbaSOystein Eftevaag break;
711*758e9fbaSOystein Eftevaag case TPM2_ECC_NIST_P521:
712*758e9fbaSOystein Eftevaag curveId = "\"NIST P-521\"";
713*758e9fbaSOystein Eftevaag max_ecc_size = (521+7)/8;
714*758e9fbaSOystein Eftevaag break;
715*758e9fbaSOystein Eftevaag default:
716*758e9fbaSOystein Eftevaag LOG_ERROR("Illegal ECC curve ID");
717*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_BAD_VALUE;
718*758e9fbaSOystein Eftevaag }
719*758e9fbaSOystein Eftevaag
720*758e9fbaSOystein Eftevaag /* compute ephemeral ecc key */
721*758e9fbaSOystein Eftevaag gcry_sexp_t ekey_spec = NULL, ekey_pair = NULL;
722*758e9fbaSOystein Eftevaag { /* scope for sexp_ecc_key */
723*758e9fbaSOystein Eftevaag char sexp_ecc_key [sizeof(SEXP_GENKEY_ECC)+strlen(curveId)
724*758e9fbaSOystein Eftevaag -1]; // -1 = (-2 for %s +1 for \0)
725*758e9fbaSOystein Eftevaag
726*758e9fbaSOystein Eftevaag if (sprintf(&sexp_ecc_key[0], SEXP_GENKEY_ECC, curveId) < 1) {
727*758e9fbaSOystein Eftevaag goto_error(r, TSS2_ESYS_RC_MEMORY, "asprintf", cleanup);
728*758e9fbaSOystein Eftevaag }
729*758e9fbaSOystein Eftevaag
730*758e9fbaSOystein Eftevaag if (gcry_sexp_build(&ekey_spec, NULL,
731*758e9fbaSOystein Eftevaag sexp_ecc_key) != GPG_ERR_NO_ERROR) {
732*758e9fbaSOystein Eftevaag goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "gcry_sexp_build", cleanup);
733*758e9fbaSOystein Eftevaag }
734*758e9fbaSOystein Eftevaag }
735*758e9fbaSOystein Eftevaag
736*758e9fbaSOystein Eftevaag if (gcry_pk_genkey (&ekey_pair, ekey_spec) != GPG_ERR_NO_ERROR) {
737*758e9fbaSOystein Eftevaag goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Create ephemeral ecc key",
738*758e9fbaSOystein Eftevaag cleanup);
739*758e9fbaSOystein Eftevaag }
740*758e9fbaSOystein Eftevaag
741*758e9fbaSOystein Eftevaag /* Get private ephemeral key d */
742*758e9fbaSOystein Eftevaag mpi_sd = gcry_sexp_find_token(ekey_pair, "d", 0);
743*758e9fbaSOystein Eftevaag if (mpi_sd == NULL) {
744*758e9fbaSOystein Eftevaag goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
745*758e9fbaSOystein Eftevaag "Get private part of ecc key", cleanup);
746*758e9fbaSOystein Eftevaag }
747*758e9fbaSOystein Eftevaag mpi_d = gcry_sexp_nth_mpi(mpi_sd, 1, GCRYMPI_FMT_USG);
748*758e9fbaSOystein Eftevaag if (mpi_d == NULL) {
749*758e9fbaSOystein Eftevaag goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
750*758e9fbaSOystein Eftevaag "Get private part of ecc key from sexp", cleanup);
751*758e9fbaSOystein Eftevaag }
752*758e9fbaSOystein Eftevaag
753*758e9fbaSOystein Eftevaag /* Construct ephemeral public key */
754*758e9fbaSOystein Eftevaag mpi_s_pub_q = gcry_sexp_find_token(ekey_pair, "public-key", 0);
755*758e9fbaSOystein Eftevaag if (mpi_s_pub_q == NULL) {
756*758e9fbaSOystein Eftevaag goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Get public part ecc key",
757*758e9fbaSOystein Eftevaag cleanup);
758*758e9fbaSOystein Eftevaag }
759*758e9fbaSOystein Eftevaag
760*758e9fbaSOystein Eftevaag if (gcry_mpi_ec_new (&ctx, mpi_s_pub_q, curveId) != GPG_ERR_NO_ERROR) {
761*758e9fbaSOystein Eftevaag goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Create ec", cleanup);
762*758e9fbaSOystein Eftevaag }
763*758e9fbaSOystein Eftevaag mpi_q = gcry_mpi_ec_get_point ("q", ctx, 1);
764*758e9fbaSOystein Eftevaag if (mpi_q == NULL) {
765*758e9fbaSOystein Eftevaag goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Get ecc point", cleanup);
766*758e9fbaSOystein Eftevaag }
767*758e9fbaSOystein Eftevaag
768*758e9fbaSOystein Eftevaag /* Check whether point is on curve */
769*758e9fbaSOystein Eftevaag if (!gcry_mpi_ec_curve_point(mpi_q, ctx)) {
770*758e9fbaSOystein Eftevaag goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Point not on curve", cleanup);
771*758e9fbaSOystein Eftevaag }
772*758e9fbaSOystein Eftevaag
773*758e9fbaSOystein Eftevaag /* Store ephemeral public key in Q */
774*758e9fbaSOystein Eftevaag if (gcry_mpi_ec_get_affine (mpi_x, mpi_y, mpi_q, ctx)) {
775*758e9fbaSOystein Eftevaag goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Point is at infinity",
776*758e9fbaSOystein Eftevaag cleanup);
777*758e9fbaSOystein Eftevaag }
778*758e9fbaSOystein Eftevaag
779*758e9fbaSOystein Eftevaag if (mpi2bin(mpi_x, &Q->x.buffer[0], max_ecc_size, max_out_size)) {
780*758e9fbaSOystein Eftevaag goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Get x part of point",
781*758e9fbaSOystein Eftevaag cleanup);
782*758e9fbaSOystein Eftevaag }
783*758e9fbaSOystein Eftevaag
784*758e9fbaSOystein Eftevaag if (mpi2bin(mpi_y, &Q->y.buffer[0], max_ecc_size, max_out_size)) {
785*758e9fbaSOystein Eftevaag goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Get y part of point",
786*758e9fbaSOystein Eftevaag cleanup);
787*758e9fbaSOystein Eftevaag }
788*758e9fbaSOystein Eftevaag
789*758e9fbaSOystein Eftevaag Q->x.size = max_ecc_size;
790*758e9fbaSOystein Eftevaag Q->y.size = max_ecc_size;
791*758e9fbaSOystein Eftevaag gcry_ctx_release(ctx);
792*758e9fbaSOystein Eftevaag
793*758e9fbaSOystein Eftevaag { /* scope for sexp_point */
794*758e9fbaSOystein Eftevaag
795*758e9fbaSOystein Eftevaag /* Get public point from TPM key */
796*758e9fbaSOystein Eftevaag char sexp_point [sizeof(SEXP_ECC_POINT) + strlen(curveId)
797*758e9fbaSOystein Eftevaag + key->publicArea.unique.ecc.x.size
798*758e9fbaSOystein Eftevaag + key->publicArea.unique.ecc.y.size
799*758e9fbaSOystein Eftevaag - 5]; /* -1 = (-4 for 2*%sb -2 for %s +1 for \0) */
800*758e9fbaSOystein Eftevaag
801*758e9fbaSOystein Eftevaag if (sprintf(&sexp_point[0], SEXP_ECC_POINT,
802*758e9fbaSOystein Eftevaag curveId, "%", "%") <1 ) {
803*758e9fbaSOystein Eftevaag goto_error(r, TSS2_ESYS_RC_MEMORY, "asprintf", cleanup);
804*758e9fbaSOystein Eftevaag }
805*758e9fbaSOystein Eftevaag
806*758e9fbaSOystein Eftevaag if ( gcry_sexp_build(&mpi_tpm_sq, NULL,
807*758e9fbaSOystein Eftevaag sexp_point,
808*758e9fbaSOystein Eftevaag key->publicArea.unique.ecc.x.size,
809*758e9fbaSOystein Eftevaag &key->publicArea.unique.ecc.x.buffer[0],
810*758e9fbaSOystein Eftevaag key->publicArea.unique.ecc.y.size,
811*758e9fbaSOystein Eftevaag &key->publicArea.unique.ecc.y.buffer[0])) {
812*758e9fbaSOystein Eftevaag goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
813*758e9fbaSOystein Eftevaag "Function gcry_mpi_scan", cleanup);
814*758e9fbaSOystein Eftevaag
815*758e9fbaSOystein Eftevaag }
816*758e9fbaSOystein Eftevaag }
817*758e9fbaSOystein Eftevaag offset = 0;
818*758e9fbaSOystein Eftevaag r = Tss2_MU_TPMS_ECC_POINT_Marshal(Q, &out_buffer[0], max_out_size, &offset);
819*758e9fbaSOystein Eftevaag return_if_error(r, "Error marshaling");
820*758e9fbaSOystein Eftevaag *out_size = offset;
821*758e9fbaSOystein Eftevaag
822*758e9fbaSOystein Eftevaag /* Multiply d and Q */
823*758e9fbaSOystein Eftevaag if (gcry_mpi_ec_new (&ctx, mpi_tpm_sq, curveId)) {
824*758e9fbaSOystein Eftevaag goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "create ec curve", cleanup);
825*758e9fbaSOystein Eftevaag }
826*758e9fbaSOystein Eftevaag mpi_tpm_q = gcry_mpi_ec_get_point ("q", ctx, 1);
827*758e9fbaSOystein Eftevaag mpi_qd = gcry_mpi_point_new(256);
828*758e9fbaSOystein Eftevaag gcry_mpi_ec_mul(mpi_qd , mpi_d, mpi_tpm_q, ctx);
829*758e9fbaSOystein Eftevaag
830*758e9fbaSOystein Eftevaag /* Store the x coordinate of d*Q in Z which will be used for KDFe */
831*758e9fbaSOystein Eftevaag if (gcry_mpi_ec_get_affine (mpi_x, mpi_y, mpi_qd, ctx)) {
832*758e9fbaSOystein Eftevaag goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
833*758e9fbaSOystein Eftevaag "Point is at infinity", cleanup);
834*758e9fbaSOystein Eftevaag }
835*758e9fbaSOystein Eftevaag
836*758e9fbaSOystein Eftevaag if (mpi2bin(mpi_x, &Z->buffer[0], max_ecc_size, TPM2_MAX_ECC_KEY_BYTES)) {
837*758e9fbaSOystein Eftevaag goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
838*758e9fbaSOystein Eftevaag "Get x coordinate d*Q", cleanup);
839*758e9fbaSOystein Eftevaag }
840*758e9fbaSOystein Eftevaag
841*758e9fbaSOystein Eftevaag Z->size = max_ecc_size;
842*758e9fbaSOystein Eftevaag LOGBLOB_DEBUG(&Z->buffer[0], Z->size, "Z (Q*d)");
843*758e9fbaSOystein Eftevaag
844*758e9fbaSOystein Eftevaag cleanup:
845*758e9fbaSOystein Eftevaag if (ctx)
846*758e9fbaSOystein Eftevaag gcry_ctx_release(ctx);
847*758e9fbaSOystein Eftevaag
848*758e9fbaSOystein Eftevaag if (mpi_x)
849*758e9fbaSOystein Eftevaag gcry_mpi_release(mpi_x);
850*758e9fbaSOystein Eftevaag
851*758e9fbaSOystein Eftevaag if (mpi_y)
852*758e9fbaSOystein Eftevaag gcry_mpi_release(mpi_y);
853*758e9fbaSOystein Eftevaag
854*758e9fbaSOystein Eftevaag if (mpi_d)
855*758e9fbaSOystein Eftevaag gcry_mpi_release(mpi_d);
856*758e9fbaSOystein Eftevaag
857*758e9fbaSOystein Eftevaag if (mpi_sd)
858*758e9fbaSOystein Eftevaag gcry_sexp_release(mpi_sd);
859*758e9fbaSOystein Eftevaag
860*758e9fbaSOystein Eftevaag if (mpi_tpm_q)
861*758e9fbaSOystein Eftevaag gcry_mpi_point_release(mpi_tpm_q);
862*758e9fbaSOystein Eftevaag
863*758e9fbaSOystein Eftevaag if (mpi_qd)
864*758e9fbaSOystein Eftevaag gcry_mpi_point_release(mpi_qd);
865*758e9fbaSOystein Eftevaag
866*758e9fbaSOystein Eftevaag if (mpi_q)
867*758e9fbaSOystein Eftevaag gcry_mpi_point_release(mpi_q);
868*758e9fbaSOystein Eftevaag
869*758e9fbaSOystein Eftevaag if (mpi_tpm_sq)
870*758e9fbaSOystein Eftevaag gcry_sexp_release(mpi_tpm_sq);
871*758e9fbaSOystein Eftevaag
872*758e9fbaSOystein Eftevaag if (mpi_s_pub_q)
873*758e9fbaSOystein Eftevaag gcry_sexp_release(mpi_s_pub_q);
874*758e9fbaSOystein Eftevaag
875*758e9fbaSOystein Eftevaag if (ekey_spec)
876*758e9fbaSOystein Eftevaag gcry_sexp_release(ekey_spec);
877*758e9fbaSOystein Eftevaag
878*758e9fbaSOystein Eftevaag if (ekey_pair)
879*758e9fbaSOystein Eftevaag gcry_sexp_release(ekey_pair);
880*758e9fbaSOystein Eftevaag
881*758e9fbaSOystein Eftevaag return r;
882*758e9fbaSOystein Eftevaag }
883*758e9fbaSOystein Eftevaag
884*758e9fbaSOystein Eftevaag /** Initialize AES context for encryption / decryption.
885*758e9fbaSOystein Eftevaag *
886*758e9fbaSOystein Eftevaag * @param[out] handle for AES context
887*758e9fbaSOystein Eftevaag * @param[in] key key used for AES.
888*758e9fbaSOystein Eftevaag * @param[in] tpm_sym_alg AES type in TSS2 notation.
889*758e9fbaSOystein Eftevaag * @param[in] key_bits Key size in bits.
890*758e9fbaSOystein Eftevaag * @param[in] tpm_mode Block cipher mode of opertion in TSS2 notation (CFB).
891*758e9fbaSOystein Eftevaag * For parameter encryption only CFB can be used.
892*758e9fbaSOystein Eftevaag * @param[in] iv_len Length of initialization vector (iv) in byte.
893*758e9fbaSOystein Eftevaag * @param[in] iv The initialization vector.
894*758e9fbaSOystein Eftevaag * @retval TSS2_RC_SUCCESS on success, or TSS2_ESYS_RC_BAD_VALUE for invalid
895*758e9fbaSOystein Eftevaag * parameters, TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto
896*758e9fbaSOystein Eftevaag * library.
897*758e9fbaSOystein Eftevaag */
898*758e9fbaSOystein Eftevaag static TSS2_RC
iesys_cryptogcry_sym_aes_init(gcry_cipher_hd_t * cipher_hd,uint8_t * key,TPM2_ALG_ID tpm_sym_alg,TPMI_AES_KEY_BITS key_bits,TPM2_ALG_ID tpm_mode,size_t iv_len,uint8_t * iv)899*758e9fbaSOystein Eftevaag iesys_cryptogcry_sym_aes_init(gcry_cipher_hd_t * cipher_hd,
900*758e9fbaSOystein Eftevaag uint8_t * key,
901*758e9fbaSOystein Eftevaag TPM2_ALG_ID tpm_sym_alg,
902*758e9fbaSOystein Eftevaag TPMI_AES_KEY_BITS key_bits,
903*758e9fbaSOystein Eftevaag TPM2_ALG_ID tpm_mode,
904*758e9fbaSOystein Eftevaag size_t iv_len, uint8_t * iv)
905*758e9fbaSOystein Eftevaag {
906*758e9fbaSOystein Eftevaag
907*758e9fbaSOystein Eftevaag LOGBLOB_TRACE(key, (key_bits + 7) / 8, "IESYS AES key");
908*758e9fbaSOystein Eftevaag LOGBLOB_TRACE(iv, iv_len, "IESYS AES iv");
909*758e9fbaSOystein Eftevaag int algo, mode, len;
910*758e9fbaSOystein Eftevaag size_t key_len = 0;
911*758e9fbaSOystein Eftevaag gcry_error_t err;
912*758e9fbaSOystein Eftevaag TSS2_RC r = TSS2_RC_SUCCESS;
913*758e9fbaSOystein Eftevaag
914*758e9fbaSOystein Eftevaag switch (tpm_sym_alg) {
915*758e9fbaSOystein Eftevaag case TPM2_ALG_AES:
916*758e9fbaSOystein Eftevaag switch (key_bits) {
917*758e9fbaSOystein Eftevaag case 128:
918*758e9fbaSOystein Eftevaag algo = GCRY_CIPHER_AES128;
919*758e9fbaSOystein Eftevaag len = 128;
920*758e9fbaSOystein Eftevaag break;
921*758e9fbaSOystein Eftevaag case 192:
922*758e9fbaSOystein Eftevaag algo = GCRY_CIPHER_AES192;
923*758e9fbaSOystein Eftevaag len = 192;
924*758e9fbaSOystein Eftevaag break;
925*758e9fbaSOystein Eftevaag case 256:
926*758e9fbaSOystein Eftevaag algo = GCRY_CIPHER_AES256;
927*758e9fbaSOystein Eftevaag len = 256;
928*758e9fbaSOystein Eftevaag break;
929*758e9fbaSOystein Eftevaag default:
930*758e9fbaSOystein Eftevaag LOG_ERROR("Illegal key length.");
931*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_BAD_VALUE;
932*758e9fbaSOystein Eftevaag }
933*758e9fbaSOystein Eftevaag switch (tpm_mode) {
934*758e9fbaSOystein Eftevaag case TPM2_ALG_CFB:
935*758e9fbaSOystein Eftevaag mode = GCRY_CIPHER_MODE_CFB;
936*758e9fbaSOystein Eftevaag break;
937*758e9fbaSOystein Eftevaag default:
938*758e9fbaSOystein Eftevaag LOG_ERROR("Illegal symmetric algorithm.");
939*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_BAD_VALUE;
940*758e9fbaSOystein Eftevaag }
941*758e9fbaSOystein Eftevaag break;
942*758e9fbaSOystein Eftevaag default:
943*758e9fbaSOystein Eftevaag LOG_ERROR("Illegal symmetric algorithm.");
944*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_BAD_VALUE;
945*758e9fbaSOystein Eftevaag }
946*758e9fbaSOystein Eftevaag key_len = (len + 7) / 8;
947*758e9fbaSOystein Eftevaag err = gcry_cipher_open(cipher_hd, algo, mode, 0);
948*758e9fbaSOystein Eftevaag if (err != GPG_ERR_NO_ERROR) {
949*758e9fbaSOystein Eftevaag LOG_ERROR("Opening gcrypt context");
950*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_GENERAL_FAILURE;
951*758e9fbaSOystein Eftevaag }
952*758e9fbaSOystein Eftevaag if (iv_len != 0) {
953*758e9fbaSOystein Eftevaag err = gcry_cipher_setiv(*cipher_hd, &iv[0], iv_len);
954*758e9fbaSOystein Eftevaag if (err != GPG_ERR_NO_ERROR) {
955*758e9fbaSOystein Eftevaag LOG_ERROR("Function gcry_cipher_setiv");
956*758e9fbaSOystein Eftevaag gcry_cipher_close(*cipher_hd);
957*758e9fbaSOystein Eftevaag r = TSS2_ESYS_RC_GENERAL_FAILURE;
958*758e9fbaSOystein Eftevaag }
959*758e9fbaSOystein Eftevaag }
960*758e9fbaSOystein Eftevaag if (r == TSS2_RC_SUCCESS) {
961*758e9fbaSOystein Eftevaag err = gcry_cipher_setkey(*cipher_hd, key, key_len);
962*758e9fbaSOystein Eftevaag if (err != GPG_ERR_NO_ERROR) {
963*758e9fbaSOystein Eftevaag LOG_ERROR("Function gcry_cipher_setkey");
964*758e9fbaSOystein Eftevaag gcry_cipher_close(*cipher_hd);
965*758e9fbaSOystein Eftevaag r = TSS2_ESYS_RC_GENERAL_FAILURE;
966*758e9fbaSOystein Eftevaag }
967*758e9fbaSOystein Eftevaag }
968*758e9fbaSOystein Eftevaag return r;
969*758e9fbaSOystein Eftevaag }
970*758e9fbaSOystein Eftevaag
971*758e9fbaSOystein Eftevaag /** Encrypt data with AES.
972*758e9fbaSOystein Eftevaag *
973*758e9fbaSOystein Eftevaag * @param[in] key key used for AES.
974*758e9fbaSOystein Eftevaag * @param[in] tpm_sym_alg AES type in TSS2 notation (must be TPM2_ALG_AES).
975*758e9fbaSOystein Eftevaag * @param[in] key_bits Key size in bits.
976*758e9fbaSOystein Eftevaag * @param[in] tpm_mode Block cipher mode of opertion in TSS2 notation.
977*758e9fbaSOystein Eftevaag * @param[in] blk_len Length Block length of AES.
978*758e9fbaSOystein Eftevaag * @param[in,out] buffer Data to be encrypted. The encrypted date will be stored
979*758e9fbaSOystein Eftevaag * in this buffer.
980*758e9fbaSOystein Eftevaag * @param[in] buffer_size size of data to be encrypted.
981*758e9fbaSOystein Eftevaag * @param[in] iv The initialization vector. The size is equal to blk_len.
982*758e9fbaSOystein Eftevaag * @retval TSS2_RC_SUCCESS on success, or TSS2_ESYS_RC_BAD_VALUE and
983*758e9fbaSOystein Eftevaag * @retval TSS2_ESYS_RC_BAD_REFERENCE for invalid parameters,
984*758e9fbaSOystein Eftevaag * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
985*758e9fbaSOystein Eftevaag */
986*758e9fbaSOystein Eftevaag TSS2_RC
iesys_cryptogcry_sym_aes_encrypt(uint8_t * key,TPM2_ALG_ID tpm_sym_alg,TPMI_AES_KEY_BITS key_bits,TPM2_ALG_ID tpm_mode,size_t blk_len,uint8_t * buffer,size_t buffer_size,uint8_t * iv)987*758e9fbaSOystein Eftevaag iesys_cryptogcry_sym_aes_encrypt(uint8_t * key,
988*758e9fbaSOystein Eftevaag TPM2_ALG_ID tpm_sym_alg,
989*758e9fbaSOystein Eftevaag TPMI_AES_KEY_BITS key_bits,
990*758e9fbaSOystein Eftevaag TPM2_ALG_ID tpm_mode,
991*758e9fbaSOystein Eftevaag size_t blk_len,
992*758e9fbaSOystein Eftevaag uint8_t * buffer,
993*758e9fbaSOystein Eftevaag size_t buffer_size,
994*758e9fbaSOystein Eftevaag uint8_t * iv)
995*758e9fbaSOystein Eftevaag {
996*758e9fbaSOystein Eftevaag gcry_cipher_hd_t cipher_hd;
997*758e9fbaSOystein Eftevaag gcry_error_t err;
998*758e9fbaSOystein Eftevaag TSS2_RC r;
999*758e9fbaSOystein Eftevaag
1000*758e9fbaSOystein Eftevaag if (key == NULL || buffer == NULL) {
1001*758e9fbaSOystein Eftevaag LOG_ERROR("Bad reference");
1002*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_BAD_REFERENCE;
1003*758e9fbaSOystein Eftevaag }
1004*758e9fbaSOystein Eftevaag
1005*758e9fbaSOystein Eftevaag r = iesys_cryptogcry_sym_aes_init(&cipher_hd, key, tpm_sym_alg,
1006*758e9fbaSOystein Eftevaag key_bits, tpm_mode, blk_len, iv);
1007*758e9fbaSOystein Eftevaag if (r != TSS2_RC_SUCCESS)
1008*758e9fbaSOystein Eftevaag return r;
1009*758e9fbaSOystein Eftevaag LOGBLOB_TRACE(buffer, buffer_size, "IESYS AES input");
1010*758e9fbaSOystein Eftevaag err = gcry_cipher_encrypt(cipher_hd, buffer, buffer_size, NULL, 0);
1011*758e9fbaSOystein Eftevaag LOGBLOB_TRACE(buffer, buffer_size, "IESYS AES output");
1012*758e9fbaSOystein Eftevaag if (err != GPG_ERR_NO_ERROR) {
1013*758e9fbaSOystein Eftevaag LOG_ERROR("Function gcry_cipher_encrypt");
1014*758e9fbaSOystein Eftevaag r = TSS2_ESYS_RC_GENERAL_FAILURE;
1015*758e9fbaSOystein Eftevaag }
1016*758e9fbaSOystein Eftevaag gcry_cipher_close(cipher_hd);
1017*758e9fbaSOystein Eftevaag return r;
1018*758e9fbaSOystein Eftevaag }
1019*758e9fbaSOystein Eftevaag
1020*758e9fbaSOystein Eftevaag /** Decrypt data with AES.
1021*758e9fbaSOystein Eftevaag *
1022*758e9fbaSOystein Eftevaag * @param[in] key key used for AES.
1023*758e9fbaSOystein Eftevaag * @param[in] tpm_sym_alg AES type in TSS2 notation (must be TPM2_ALG_AES).
1024*758e9fbaSOystein Eftevaag * @param[in] key_bits Key size in bits.
1025*758e9fbaSOystein Eftevaag * @param[in] tpm_mode Block cipher mode of opertion in TSS2 notation (CFB).
1026*758e9fbaSOystein Eftevaag * @param[in] blk_len Length Block length of AES.
1027*758e9fbaSOystein Eftevaag * @param[in,out] buffer Data to be decrypted. The decrypted date will be stored
1028*758e9fbaSOystein Eftevaag * in this buffer.
1029*758e9fbaSOystein Eftevaag * @param[in] buffer_size size of data to be encrypted.
1030*758e9fbaSOystein Eftevaag * @param[in] iv The initialization vector. The size is equal to blk_len.
1031*758e9fbaSOystein Eftevaag * @retval TSS2_RC_SUCCESS on success, or TSS2_ESYS_RC_BAD_VALUE and
1032*758e9fbaSOystein Eftevaag * @retval TSS2_ESYS_RC_BAD_REFERENCE for invalid parameters,
1033*758e9fbaSOystein Eftevaag * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
1034*758e9fbaSOystein Eftevaag */
1035*758e9fbaSOystein Eftevaag TSS2_RC
iesys_cryptogcry_sym_aes_decrypt(uint8_t * key,TPM2_ALG_ID tpm_sym_alg,TPMI_AES_KEY_BITS key_bits,TPM2_ALG_ID tpm_mode,size_t blk_len,uint8_t * buffer,size_t buffer_size,uint8_t * iv)1036*758e9fbaSOystein Eftevaag iesys_cryptogcry_sym_aes_decrypt(uint8_t * key,
1037*758e9fbaSOystein Eftevaag TPM2_ALG_ID tpm_sym_alg,
1038*758e9fbaSOystein Eftevaag TPMI_AES_KEY_BITS key_bits,
1039*758e9fbaSOystein Eftevaag TPM2_ALG_ID tpm_mode,
1040*758e9fbaSOystein Eftevaag size_t blk_len,
1041*758e9fbaSOystein Eftevaag uint8_t * buffer,
1042*758e9fbaSOystein Eftevaag size_t buffer_size,
1043*758e9fbaSOystein Eftevaag uint8_t * iv)
1044*758e9fbaSOystein Eftevaag {
1045*758e9fbaSOystein Eftevaag gcry_cipher_hd_t cipher_hd;
1046*758e9fbaSOystein Eftevaag gcry_error_t err;
1047*758e9fbaSOystein Eftevaag TSS2_RC r;
1048*758e9fbaSOystein Eftevaag
1049*758e9fbaSOystein Eftevaag if (key == NULL || buffer == NULL) {
1050*758e9fbaSOystein Eftevaag LOG_ERROR("Bad reference");
1051*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_BAD_REFERENCE;
1052*758e9fbaSOystein Eftevaag }
1053*758e9fbaSOystein Eftevaag
1054*758e9fbaSOystein Eftevaag if (tpm_sym_alg != TPM2_ALG_AES) {
1055*758e9fbaSOystein Eftevaag LOG_ERROR("AES expected");
1056*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_BAD_VALUE;
1057*758e9fbaSOystein Eftevaag }
1058*758e9fbaSOystein Eftevaag
1059*758e9fbaSOystein Eftevaag r = iesys_cryptogcry_sym_aes_init(&cipher_hd, key, tpm_sym_alg,
1060*758e9fbaSOystein Eftevaag key_bits, tpm_mode, blk_len, iv);
1061*758e9fbaSOystein Eftevaag if (r != TSS2_RC_SUCCESS)
1062*758e9fbaSOystein Eftevaag return r;
1063*758e9fbaSOystein Eftevaag err = gcry_cipher_decrypt(cipher_hd, buffer, buffer_size, NULL, 0);
1064*758e9fbaSOystein Eftevaag if (err != GPG_ERR_NO_ERROR) {
1065*758e9fbaSOystein Eftevaag LOG_ERROR("Function gcry_cipher_decrypt");
1066*758e9fbaSOystein Eftevaag r = TSS2_ESYS_RC_GENERAL_FAILURE;
1067*758e9fbaSOystein Eftevaag }
1068*758e9fbaSOystein Eftevaag gcry_cipher_close(cipher_hd);
1069*758e9fbaSOystein Eftevaag return r;
1070*758e9fbaSOystein Eftevaag }
1071*758e9fbaSOystein Eftevaag
1072*758e9fbaSOystein Eftevaag /** Initialize gcrypt crypto backend.
1073*758e9fbaSOystein Eftevaag *
1074*758e9fbaSOystein Eftevaag * Initialize gcrypt internal tables.
1075*758e9fbaSOystein Eftevaag *
1076*758e9fbaSOystein Eftevaag * @retval TSS2_RC_SUCCESS ong success.
1077*758e9fbaSOystein Eftevaag * @retval TSS2_ESYS_RC_GENERAL_FAILURE for version mismatch.
1078*758e9fbaSOystein Eftevaag */
1079*758e9fbaSOystein Eftevaag TSS2_RC
iesys_cryptogcry_init()1080*758e9fbaSOystein Eftevaag iesys_cryptogcry_init() {
1081*758e9fbaSOystein Eftevaag if (!gcry_check_version (GCRYPT_VERSION))
1082*758e9fbaSOystein Eftevaag {
1083*758e9fbaSOystein Eftevaag LOG_ERROR("Version mismatch for gcrypt");
1084*758e9fbaSOystein Eftevaag return TSS2_ESYS_RC_GENERAL_FAILURE;
1085*758e9fbaSOystein Eftevaag }
1086*758e9fbaSOystein Eftevaag return TSS2_RC_SUCCESS;
1087*758e9fbaSOystein Eftevaag }
1088