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