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 <openssl/evp.h>
12 #include <openssl/aes.h>
13 #include <openssl/rsa.h>
14 #include <openssl/engine.h>
15 #include <stdio.h>
16
17 #include "tss2_esys.h"
18
19 #include "esys_crypto.h"
20 #include "esys_crypto_ossl.h"
21
22 #include "esys_iutil.h"
23 #include "esys_mu.h"
24 #define LOGMODULE esys_crypto
25 #include "util/log.h"
26 #include "util/aux_util.h"
27
28 static int
iesys_bn2binpad(const BIGNUM * bn,unsigned char * bin,int bin_length)29 iesys_bn2binpad(const BIGNUM *bn, unsigned char *bin, int bin_length)
30 {
31 int len_bn = BN_num_bytes(bn);
32 int offset = bin_length - len_bn;
33 memset(bin,0,offset);
34 BN_bn2bin(bn, bin + offset);
35 return 1;
36 }
37
38 /** Context to hold temporary values for iesys_crypto */
39 typedef struct _IESYS_CRYPTO_CONTEXT {
40 enum {
41 IESYS_CRYPTOSSL_TYPE_HASH = 1,
42 IESYS_CRYPTOSSL_TYPE_HMAC,
43 } type; /**< The type of context to hold; hash or hmac */
44 union {
45 struct {
46 EVP_MD_CTX *ossl_context;
47 const EVP_MD *ossl_hash_alg;
48 size_t hash_len;
49 } hash; /**< the state variables for a hash context */
50 struct {
51 EVP_MD_CTX *ossl_context;
52 const EVP_MD *ossl_hash_alg;
53 size_t hmac_len;
54 } hmac; /**< the state variables for an hmac context */
55 };
56 } IESYS_CRYPTOSSL_CONTEXT;
57
58 const EVP_MD *
get_ossl_hash_md(TPM2_ALG_ID hashAlg)59 get_ossl_hash_md(TPM2_ALG_ID hashAlg)
60 {
61 switch (hashAlg) {
62 case TPM2_ALG_SHA1:
63 return EVP_sha1();
64 break;
65 case TPM2_ALG_SHA256:
66 return EVP_sha256();
67 break;
68 case TPM2_ALG_SHA384:
69 return EVP_sha384();
70 break;
71 case TPM2_ALG_SHA512:
72 return EVP_sha512();
73 break;
74 default:
75 return NULL;
76 }
77 }
78
79 /** Provide the context for the computation of a hash digest.
80 *
81 * The context will be created and initialized according to the hash function.
82 * @param[out] context The created context (callee-allocated).
83 * @param[in] hashAlg The hash algorithm for the creation of the context.
84 * @retval TSS2_RC_SUCCESS on success.
85 * @retval TSS2_ESYS_RC_BAD_VALUE or TSS2_ESYS_RC_BAD_REFERENCE for invalid parameters.
86 * @retval TSS2_ESYS_RC_MEMORY Memory cannot be allocated.
87 * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
88 */
89 TSS2_RC
iesys_cryptossl_hash_start(IESYS_CRYPTO_CONTEXT_BLOB ** context,TPM2_ALG_ID hashAlg)90 iesys_cryptossl_hash_start(IESYS_CRYPTO_CONTEXT_BLOB ** context,
91 TPM2_ALG_ID hashAlg)
92 {
93 TSS2_RC r = TSS2_RC_SUCCESS;
94 LOG_TRACE("call: context=%p hashAlg=%"PRIu16, context, hashAlg);
95 return_if_null(context, "Context is NULL", TSS2_ESYS_RC_BAD_REFERENCE);
96 return_if_null(context, "Null-Pointer passed for context", TSS2_ESYS_RC_BAD_REFERENCE);
97 IESYS_CRYPTOSSL_CONTEXT *mycontext;
98 mycontext = calloc(1, sizeof(IESYS_CRYPTOSSL_CONTEXT));
99 return_if_null(mycontext, "Out of Memory", TSS2_ESYS_RC_MEMORY);
100 mycontext->type = IESYS_CRYPTOSSL_TYPE_HASH;
101
102 if (!(mycontext->hash.ossl_hash_alg = get_ossl_hash_md(hashAlg))) {
103 goto_error(r, TSS2_ESYS_RC_NOT_IMPLEMENTED,
104 "Unsupported hash algorithm (%"PRIu16")", cleanup, hashAlg);
105 }
106
107 if (iesys_crypto_hash_get_digest_size(hashAlg, &mycontext->hash.hash_len)) {
108 goto_error(r, TSS2_ESYS_RC_NOT_IMPLEMENTED,
109 "Unsupported hash algorithm (%"PRIu16")", cleanup, hashAlg);
110 }
111
112 if (!(mycontext->hash.ossl_context = EVP_MD_CTX_create())) {
113 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Error EVP_MD_CTX_create", cleanup);
114 }
115
116 if (1 != EVP_DigestInit_ex(mycontext->hash.ossl_context,
117 mycontext->hash.ossl_hash_alg,
118 NULL)) {
119 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Errror EVP_DigestInit_ex", cleanup);
120 }
121
122 *context = (IESYS_CRYPTO_CONTEXT_BLOB *) mycontext;
123
124 return TSS2_RC_SUCCESS;
125
126 cleanup:
127 if (mycontext->hash.ossl_context)
128 EVP_MD_CTX_destroy(mycontext->hash.ossl_context);
129 SAFE_FREE(mycontext);
130
131 return r;
132 }
133
134 /** Update the digest value of a digest object from a byte buffer.
135 *
136 * The context of a digest object will be updated according to the hash
137 * algorithm of the context. <
138 * @param[in,out] context The context of the digest object which will be updated.
139 * @param[in] buffer The data for the update.
140 * @param[in] size The size of the data buffer.
141 * @retval TSS2_RC_SUCCESS on success.
142 * @retval TSS2_ESYS_RC_BAD_REFERENCE for invalid parameters.
143 */
144 TSS2_RC
iesys_cryptossl_hash_update(IESYS_CRYPTO_CONTEXT_BLOB * context,const uint8_t * buffer,size_t size)145 iesys_cryptossl_hash_update(IESYS_CRYPTO_CONTEXT_BLOB * context,
146 const uint8_t * buffer, size_t size)
147 {
148 LOG_TRACE("called for context %p, buffer %p and size %zd", context, buffer,
149 size);
150 if (context == NULL || buffer == NULL) {
151 LOG_ERROR("Null-Pointer passed");
152 return TSS2_ESYS_RC_BAD_REFERENCE;
153 }
154 IESYS_CRYPTOSSL_CONTEXT *mycontext = (IESYS_CRYPTOSSL_CONTEXT *) context;
155 if (mycontext->type != IESYS_CRYPTOSSL_TYPE_HASH) {
156 LOG_ERROR("bad context");
157 return TSS2_ESYS_RC_BAD_REFERENCE;
158 }
159
160 LOGBLOB_TRACE(buffer, size, "Updating hash with");
161
162 if (1 != EVP_DigestUpdate(mycontext->hash.ossl_context, buffer, size)) {
163 return_error(TSS2_ESYS_RC_GENERAL_FAILURE, "OSSL hash update");
164 }
165
166 return TSS2_RC_SUCCESS;
167 }
168
169 /** Update the digest value of a digest object from a TPM2B object.
170 *
171 * The context of a digest object will be updated according to the hash
172 * algorithm of the context.
173 * @param[in,out] context The context of the digest object which will be updated.
174 * @param[in] b The TPM2B object for the update.
175 * @retval TSS2_RC_SUCCESS on success.
176 * @retval TSS2_ESYS_RC_BAD_REFERENCE for invalid parameters.
177 */
178 TSS2_RC
iesys_cryptossl_hash_update2b(IESYS_CRYPTO_CONTEXT_BLOB * context,TPM2B * b)179 iesys_cryptossl_hash_update2b(IESYS_CRYPTO_CONTEXT_BLOB * context, TPM2B * b)
180 {
181 LOG_TRACE("called for context-pointer %p and 2b-pointer %p", context, b);
182 if (context == NULL || b == NULL) {
183 LOG_ERROR("Null-Pointer passed");
184 return TSS2_ESYS_RC_BAD_REFERENCE;
185 }
186 TSS2_RC ret = iesys_cryptossl_hash_update(context, &b->buffer[0], b->size);
187 return ret;
188 }
189
190 /** Get the digest value of a digest object and close the context.
191 *
192 * The digest value will written to a passed buffer and the resources of the
193 * digest object are released.
194 * @param[in,out] context The context of the digest object to be released
195 * @param[out] buffer The buffer for the digest value (caller-allocated).
196 * @param[out] size The size of the digest.
197 * @retval TSS2_RC_SUCCESS on success.
198 * @retval TSS2_ESYS_RC_BAD_REFERENCE for invalid parameters.
199 * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
200 */
201 TSS2_RC
iesys_cryptossl_hash_finish(IESYS_CRYPTO_CONTEXT_BLOB ** context,uint8_t * buffer,size_t * size)202 iesys_cryptossl_hash_finish(IESYS_CRYPTO_CONTEXT_BLOB ** context,
203 uint8_t * buffer, size_t * size)
204 {
205 unsigned int digest_size = 0;
206
207 LOG_TRACE("called for context-pointer %p, buffer %p and size-pointer %p",
208 context, buffer, size);
209 if (context == NULL || *context == NULL || buffer == NULL || size == NULL) {
210 return_error(TSS2_ESYS_RC_BAD_REFERENCE, "Null-Pointer passed");
211 }
212 IESYS_CRYPTOSSL_CONTEXT *mycontext = * context;
213 if (mycontext->type != IESYS_CRYPTOSSL_TYPE_HASH) {
214 return_error(TSS2_ESYS_RC_BAD_REFERENCE, "bad context");
215 }
216
217 if (*size < mycontext->hash.hash_len) {
218 return_error(TSS2_ESYS_RC_BAD_SIZE, "Buffer too small");
219 }
220
221 if (1 != EVP_DigestFinal_ex(mycontext->hash.ossl_context, buffer, &digest_size)) {
222 return_error(TSS2_ESYS_RC_GENERAL_FAILURE, "Ossl error.");
223 }
224
225 if (digest_size != mycontext->hash.hash_len) {
226 return_error(TSS2_ESYS_RC_GENERAL_FAILURE,
227 "Invalid size computed by EVP_DigestFinal_ex");
228 }
229
230 LOGBLOB_TRACE(buffer, mycontext->hash.hash_len, "read hash result");
231
232 *size = mycontext->hash.hash_len;
233 EVP_MD_CTX_destroy(mycontext->hash.ossl_context);
234 free(mycontext);
235 *context = NULL;
236
237 return TSS2_RC_SUCCESS;
238 }
239
240 /** Release the resources of a digest object.
241 *
242 * The assigned resources will be released and the context will be set to NULL.
243 * @param[in,out] context The context of the digest object.
244 */
245 void
iesys_cryptossl_hash_abort(IESYS_CRYPTO_CONTEXT_BLOB ** context)246 iesys_cryptossl_hash_abort(IESYS_CRYPTO_CONTEXT_BLOB ** context)
247 {
248 LOG_TRACE("called for context-pointer %p", context);
249 if (context == NULL || *context == NULL) {
250 LOG_DEBUG("Null-Pointer passed");
251 return;
252 }
253 IESYS_CRYPTOSSL_CONTEXT *mycontext =
254 (IESYS_CRYPTOSSL_CONTEXT *) * context;
255 if (mycontext->type != IESYS_CRYPTOSSL_TYPE_HASH) {
256 LOG_DEBUG("bad context");
257 return;
258 }
259
260 EVP_MD_CTX_destroy(mycontext->hash.ossl_context);
261 free(mycontext);
262 *context = NULL;
263 }
264
265 /* HMAC */
266
267 /** Provide the context an HMAC digest object from a byte buffer key.
268 *
269 * The context will be created and initialized according to the hash function
270 * and the used HMAC key.
271 * @param[out] context The created context (callee-allocated).
272 * @param[in] hmacAlg The hash algorithm for the HMAC computation.
273 * @param[in] key The byte buffer of the HMAC key.
274 * @param[in] size The size of the HMAC key.
275 * @retval TSS2_RC_SUCCESS on success.
276 * @retval TSS2_ESYS_RC_BAD_REFERENCE for invalid parameters.
277 * @retval TSS2_ESYS_RC_MEMORY Memory cannot be allocated.
278 * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
279 */
280 TSS2_RC
iesys_cryptossl_hmac_start(IESYS_CRYPTO_CONTEXT_BLOB ** context,TPM2_ALG_ID hashAlg,const uint8_t * key,size_t size)281 iesys_cryptossl_hmac_start(IESYS_CRYPTO_CONTEXT_BLOB ** context,
282 TPM2_ALG_ID hashAlg,
283 const uint8_t * key, size_t size)
284 {
285 TSS2_RC r = TSS2_RC_SUCCESS;
286 EVP_PKEY *hkey = NULL;
287
288 LOG_TRACE("called for context-pointer %p and hmacAlg %d", context, hashAlg);
289 LOGBLOB_TRACE(key, size, "Starting hmac with");
290 if (context == NULL || key == NULL) {
291 return_error(TSS2_ESYS_RC_BAD_REFERENCE,
292 "Null-Pointer passed in for context");
293 }
294 IESYS_CRYPTOSSL_CONTEXT *mycontext = calloc(1, sizeof(IESYS_CRYPTOSSL_CONTEXT));
295 return_if_null(mycontext, "Out of Memory", TSS2_ESYS_RC_MEMORY);
296
297 if (!(mycontext->hmac.ossl_hash_alg = get_ossl_hash_md(hashAlg))) {
298 goto_error(r, TSS2_ESYS_RC_NOT_IMPLEMENTED,
299 "Unsupported hash algorithm (%"PRIu16")", cleanup, hashAlg);
300 }
301
302 if (iesys_crypto_hash_get_digest_size(hashAlg, &mycontext->hmac.hmac_len)) {
303 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
304 "Unsupported hash algorithm (%"PRIu16")", cleanup, hashAlg);
305 }
306
307 if (!(mycontext->hmac.ossl_context = EVP_MD_CTX_create())) {
308 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
309 "Error EVP_MD_CTX_create", cleanup);
310 }
311
312 if (!(hkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, key, size))) {
313 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
314 "EVP_PKEY_new_mac_key", cleanup);
315 }
316
317 if(1 != EVP_DigestSignInit(mycontext->hmac.ossl_context, NULL,
318 mycontext->hmac.ossl_hash_alg, NULL, hkey)) {
319 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
320 "DigestSignInit", cleanup);
321 }
322
323 mycontext->type = IESYS_CRYPTOSSL_TYPE_HMAC;
324
325 *context = (IESYS_CRYPTO_CONTEXT_BLOB *) mycontext;
326
327 EVP_PKEY_free(hkey);
328
329 return TSS2_RC_SUCCESS;
330
331 cleanup:
332 if (mycontext->hmac.ossl_context)
333 EVP_MD_CTX_destroy(mycontext->hmac.ossl_context);
334 if(hkey)
335 EVP_PKEY_free(hkey);
336 SAFE_FREE(mycontext);
337 return r;
338 }
339
340 /** Update and HMAC digest value from a byte buffer.
341 *
342 * The context of a digest object will be updated according to the hash
343 * algorithm and the key of the context.
344 * @param[in,out] context The context of the digest object which will be updated.
345 * @param[in] buffer The data for the update.
346 * @param[in] size The size of the data buffer.
347 * @retval TSS2_RC_SUCCESS on success.
348 * @retval TSS2_ESYS_RC_BAD_REFERENCE for invalid parameters.
349 */
350 TSS2_RC
iesys_cryptossl_hmac_update(IESYS_CRYPTO_CONTEXT_BLOB * context,const uint8_t * buffer,size_t size)351 iesys_cryptossl_hmac_update(IESYS_CRYPTO_CONTEXT_BLOB * context,
352 const uint8_t * buffer, size_t size)
353 {
354 LOG_TRACE("called for context %p, buffer %p and size %zd",
355 context, buffer, size);
356 if (context == NULL || buffer == NULL) {
357 return_error(TSS2_ESYS_RC_BAD_REFERENCE, "Null-Pointer passed");
358 }
359 IESYS_CRYPTOSSL_CONTEXT *mycontext = (IESYS_CRYPTOSSL_CONTEXT *) context;
360 if (mycontext->type != IESYS_CRYPTOSSL_TYPE_HMAC) {
361 return_error(TSS2_ESYS_RC_BAD_REFERENCE, "bad context");
362 }
363
364 LOGBLOB_TRACE(buffer, size, "Updating hmac with");
365
366 /* Call update with the message */
367 if(1 != EVP_DigestSignUpdate(mycontext->hmac.ossl_context, buffer, size)) {
368 return_error(TSS2_ESYS_RC_GENERAL_FAILURE, "OSSL HMAC update");
369 }
370
371 return TSS2_RC_SUCCESS;
372 }
373
374 /** Update and HMAC digest value from a TPM2B object.
375 *
376 * The context of a digest object will be updated according to the hash
377 * algorithm and the key of the context.
378 * @param[in,out] context The context of the digest object which will be updated.
379 * @param[in] b The TPM2B object for the update.
380 * @retval TSS2_RC_SUCCESS on success.
381 * @retval TSS2_ESYS_RC_BAD_REFERENCE for invalid parameters.
382 */
383 TSS2_RC
iesys_cryptossl_hmac_update2b(IESYS_CRYPTO_CONTEXT_BLOB * context,TPM2B * b)384 iesys_cryptossl_hmac_update2b(IESYS_CRYPTO_CONTEXT_BLOB * context, TPM2B * b)
385 {
386 LOG_TRACE("called for context-pointer %p and 2b-pointer %p", context, b);
387 if (context == NULL || b == NULL) {
388 return_error(TSS2_ESYS_RC_BAD_REFERENCE, "Null-Pointer passed");
389 }
390 TSS2_RC ret = iesys_cryptossl_hmac_update(context, &b->buffer[0], b->size);
391 return ret;
392 }
393
394 /** Write the HMAC digest value to a byte buffer and close the context.
395 *
396 * The digest value will written to a passed buffer and the resources of the
397 * HMAC object are released.
398 * @param[in,out] context The context of the HMAC object.
399 * @param[out] buffer The buffer for the digest value (caller-allocated).
400 * @param[out] size The size of the digest.
401 * @retval TSS2_RC_SUCCESS on success.
402 * @retval TSS2_ESYS_RC_BAD_REFERENCE for invalid parameters.
403 * @retval TSS2_ESYS_RC_BAD_SIZE If the size passed is lower than the HMAC length.
404 * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
405 */
406 TSS2_RC
iesys_cryptossl_hmac_finish(IESYS_CRYPTO_CONTEXT_BLOB ** context,uint8_t * buffer,size_t * size)407 iesys_cryptossl_hmac_finish(IESYS_CRYPTO_CONTEXT_BLOB ** context,
408 uint8_t * buffer, size_t * size)
409 {
410
411 TSS2_RC r = TSS2_RC_SUCCESS;
412
413 LOG_TRACE("called for context-pointer %p, buffer %p and size-pointer %p",
414 context, buffer, size);
415 if (context == NULL || *context == NULL || buffer == NULL || size == NULL) {
416 return_error(TSS2_ESYS_RC_BAD_REFERENCE, "Null-Pointer passed");
417 }
418 IESYS_CRYPTOSSL_CONTEXT *mycontext =
419 (IESYS_CRYPTOSSL_CONTEXT *) * context;
420 if (mycontext->type != IESYS_CRYPTOSSL_TYPE_HMAC) {
421 return_error(TSS2_ESYS_RC_BAD_REFERENCE, "bad context");
422 }
423
424 if (*size < mycontext->hmac.hmac_len) {
425 return_error(TSS2_ESYS_RC_BAD_SIZE, "Buffer too small");
426 }
427
428 if (1 != EVP_DigestSignFinal(mycontext->hmac.ossl_context, buffer, size)) {
429 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "DigestSignFinal", cleanup);
430 }
431
432 LOGBLOB_TRACE(buffer, *size, "read hmac result");
433
434 cleanup:
435 EVP_MD_CTX_destroy(mycontext->hmac.ossl_context);
436 SAFE_FREE(mycontext);
437 *context = NULL;
438 return r;
439 }
440
441 /** Write the HMAC digest value to a TPM2B object and close the context.
442 *
443 * The digest value will written to a passed TPM2B object and the resources of
444 * the HMAC object are released.
445 * @param[in,out] context The context of the HMAC object.
446 * @param[out] hmac The buffer for the digest value (caller-allocated).
447 * @retval TSS2_RC_SUCCESS on success.
448 * @retval TSS2_ESYS_RC_BAD_REFERENCE for invalid parameters.
449 * @retval TSS2_ESYS_RC_BAD_SIZE if the size passed is lower than the HMAC length.
450 * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
451 */
452 TSS2_RC
iesys_cryptossl_hmac_finish2b(IESYS_CRYPTO_CONTEXT_BLOB ** context,TPM2B * hmac)453 iesys_cryptossl_hmac_finish2b(IESYS_CRYPTO_CONTEXT_BLOB ** context, TPM2B * hmac)
454 {
455 LOG_TRACE("called for context-pointer %p and 2b-pointer %p", context, hmac);
456 if (context == NULL || *context == NULL || hmac == NULL) {
457 return_error(TSS2_ESYS_RC_BAD_REFERENCE, "Null-Pointer passed");
458 }
459 size_t s = hmac->size;
460 TSS2_RC ret = iesys_cryptossl_hmac_finish(context, &hmac->buffer[0], &s);
461 hmac->size = s;
462 return ret;
463 }
464
465 /** Release the resources of an HAMC object.
466 *
467 * The assigned resources will be released and the context will be set to NULL.
468 * @param[in,out] context The context of the HMAC object.
469 */
470 void
iesys_cryptossl_hmac_abort(IESYS_CRYPTO_CONTEXT_BLOB ** context)471 iesys_cryptossl_hmac_abort(IESYS_CRYPTO_CONTEXT_BLOB ** context)
472 {
473 LOG_TRACE("called for context-pointer %p", context);
474 if (context == NULL || *context == NULL) {
475 LOG_DEBUG("Null-Pointer passed");
476 return;
477 }
478 if (*context != NULL) {
479 IESYS_CRYPTOSSL_CONTEXT *mycontext =
480 (IESYS_CRYPTOSSL_CONTEXT *) * context;
481 if (mycontext->type != IESYS_CRYPTOSSL_TYPE_HMAC) {
482 LOG_DEBUG("bad context");
483 return;
484 }
485
486 EVP_MD_CTX_destroy(mycontext->hmac.ossl_context);
487
488 free(mycontext);
489 *context = NULL;
490 }
491 }
492
493 /** Compute random TPM2B data.
494 *
495 * The random data will be generated and written to a passed TPM2B structure.
496 * @param[out] nonce The TPM2B structure for the random data (caller-allocated).
497 * @param[in] num_bytes The number of bytes to be generated.
498 * @retval TSS2_RC_SUCCESS on success.
499 *
500 * NOTE: the TPM should not be used to obtain the random data
501 */
502 TSS2_RC
iesys_cryptossl_random2b(TPM2B_NONCE * nonce,size_t num_bytes)503 iesys_cryptossl_random2b(TPM2B_NONCE * nonce, size_t num_bytes)
504 {
505 const RAND_METHOD *rand_save = RAND_get_rand_method();
506
507 if (num_bytes == 0) {
508 nonce->size = sizeof(TPMU_HA);
509 } else {
510 nonce->size = num_bytes;
511 }
512
513 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
514 RAND_set_rand_method(RAND_OpenSSL());
515 #else
516 RAND_set_rand_method(RAND_SSLeay());
517 #endif
518 if (1 != RAND_bytes(&nonce->buffer[0], nonce->size)) {
519 RAND_set_rand_method(rand_save);
520 return_error(TSS2_ESYS_RC_GENERAL_FAILURE,
521 "Failure in random number generator.");
522 }
523 RAND_set_rand_method(rand_save);
524 return TSS2_RC_SUCCESS;
525 }
526
527 /** Encryption of a buffer using a public (RSA) key.
528 *
529 * Encrypting a buffer using a public key is used for example during
530 * Esys_StartAuthSession in order to encrypt the salt value.
531 * @param[in] key The key to be used for encryption.
532 * @param[in] in_size The size of the buffer to be encrypted.
533 * @param[in] in_buffer The data buffer to be encrypted.
534 * @param[in] max_out_size The maximum size for the output encrypted buffer.
535 * @param[out] out_buffer The encrypted buffer.
536 * @param[out] out_size The size of the encrypted output.
537 * @param[in] label The label used in the encryption scheme.
538 * @retval TSS2_RC_SUCCESS on success
539 * @retval TSS2_ESYS_RC_BAD_VALUE The algorithm of key is not implemented.
540 * @retval TSS2_ESYS_RC_GENERAL_FAILURE The internal crypto engine failed.
541 */
542 TSS2_RC
iesys_cryptossl_pk_encrypt(TPM2B_PUBLIC * pub_tpm_key,size_t in_size,BYTE * in_buffer,size_t max_out_size,BYTE * out_buffer,size_t * out_size,const char * label)543 iesys_cryptossl_pk_encrypt(TPM2B_PUBLIC * pub_tpm_key,
544 size_t in_size,
545 BYTE * in_buffer,
546 size_t max_out_size,
547 BYTE * out_buffer,
548 size_t * out_size, const char *label)
549 {
550 const RAND_METHOD *rand_save = RAND_get_rand_method();
551 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
552 RAND_set_rand_method(RAND_OpenSSL());
553 #else
554 RAND_set_rand_method(RAND_SSLeay());
555 #endif
556
557 TSS2_RC r = TSS2_RC_SUCCESS;
558 const EVP_MD * hashAlg = NULL;
559 RSA * rsa_key = NULL;
560 EVP_PKEY *evp_rsa_key = NULL;
561 EVP_PKEY_CTX *ctx = NULL;
562 BIGNUM* bne = NULL;
563 int padding;
564 char *label_copy = NULL;
565
566 if (!(hashAlg = get_ossl_hash_md(pub_tpm_key->publicArea.nameAlg))) {
567 LOG_ERROR("Unsupported hash algorithm (%"PRIu16")",
568 pub_tpm_key->publicArea.nameAlg);
569 RAND_set_rand_method(rand_save);
570 return TSS2_ESYS_RC_NOT_IMPLEMENTED;
571 }
572
573 if (!(bne = BN_new())) {
574 goto_error(r, TSS2_ESYS_RC_MEMORY,
575 "Could not allocate Big Number", cleanup);
576 }
577
578 switch (pub_tpm_key->publicArea.parameters.rsaDetail.scheme.scheme) {
579 case TPM2_ALG_NULL:
580 padding = RSA_NO_PADDING;
581 break;
582 case TPM2_ALG_RSAES:
583 padding = RSA_PKCS1_PADDING;
584 break;
585 case TPM2_ALG_OAEP:
586 padding = RSA_PKCS1_OAEP_PADDING;
587 break;
588 default:
589 goto_error(r, TSS2_ESYS_RC_BAD_VALUE, "Illegal RSA scheme", cleanup);
590 }
591
592 UINT32 exp;
593 if (pub_tpm_key->publicArea.parameters.rsaDetail.exponent == 0)
594 exp = 65537;
595 else
596 exp = pub_tpm_key->publicArea.parameters.rsaDetail.exponent;
597 if (1 != BN_set_word(bne, exp)) {
598 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
599 "Could not set exponent.", cleanup);
600 }
601
602 if (!(rsa_key = RSA_new())) {
603 goto_error(r, TSS2_ESYS_RC_MEMORY,
604 "Could not allocate RSA key", cleanup);
605 }
606
607 if (1 != RSA_generate_key_ex(rsa_key,
608 pub_tpm_key->publicArea.parameters.rsaDetail.keyBits,
609 bne, NULL)) {
610 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Could not generate RSA key",
611 cleanup);
612 }
613
614 if (!(evp_rsa_key = EVP_PKEY_new())) {
615 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
616 "Could not create evp key.", cleanup);
617 }
618 #if OPENSSL_VERSION_NUMBER < 0x10100000L
619 if (!BN_bin2bn(pub_tpm_key->publicArea.unique.rsa.buffer,
620 pub_tpm_key->publicArea.unique.rsa.size,
621 rsa_key->n)) {
622 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
623 "Could not create rsa n.", cleanup);
624 }
625 #else
626 BIGNUM *n = NULL;
627 if (!(n = BN_bin2bn(pub_tpm_key->publicArea.unique.rsa.buffer,
628 pub_tpm_key->publicArea.unique.rsa.size,
629 NULL))) {
630 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
631 "Could not create rsa n.", cleanup);
632 }
633
634 if (1 != RSA_set0_key(rsa_key, n, NULL, NULL)) {
635 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
636 "Could not set rsa n.", cleanup);
637 }
638 #endif
639
640 if (1 != EVP_PKEY_set1_RSA(evp_rsa_key, rsa_key)) {
641 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
642 "Could not set rsa key.", cleanup);
643 }
644
645 if (!(ctx = EVP_PKEY_CTX_new(evp_rsa_key, NULL))) {
646 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
647 "Could not create evp context.", cleanup);
648 }
649
650 if (1 != EVP_PKEY_encrypt_init(ctx)) {
651 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
652 "Could not init encrypt context.", cleanup);
653 }
654
655 if (1 != EVP_PKEY_CTX_set_rsa_padding(ctx, padding)) {
656 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
657 "Could not set RSA passing.", cleanup);
658 }
659
660 label_copy = OPENSSL_strdup(label);
661 if (!label_copy) {
662 goto_error(r, TSS2_ESYS_RC_MEMORY,
663 "Could not duplicate OAEP label", cleanup);
664 }
665
666 if (1 != EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, label_copy, strlen(label_copy)+1)) {
667 OPENSSL_free(label_copy);
668 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
669 "Could not set RSA label.", cleanup);
670 }
671
672 if (1 != EVP_PKEY_CTX_set_rsa_oaep_md(ctx, hashAlg)) {
673 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
674 "Could not set hash algorithm.", cleanup);
675 }
676
677 /* Determine out size */
678 if (1 != EVP_PKEY_encrypt(ctx, NULL, out_size, in_buffer, in_size)) {
679 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
680 "Could not determine ciper size.", cleanup);
681 }
682
683 if ((size_t)*out_size > max_out_size) {
684 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
685 "Encrypted data too big", cleanup);
686 }
687
688 /* Encrypt data */
689 if (1 != EVP_PKEY_encrypt(ctx, out_buffer, out_size, in_buffer, in_size)) {
690 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
691 "Could not encrypt data.", cleanup);
692 }
693
694 r = TSS2_RC_SUCCESS;
695
696 cleanup:
697 OSSL_FREE(ctx, EVP_PKEY_CTX);
698 OSSL_FREE(evp_rsa_key, EVP_PKEY);
699 OSSL_FREE(rsa_key, RSA);
700 OSSL_FREE(bne, BN);
701 RAND_set_rand_method(rand_save);
702 return r;
703 }
704
705 /** Computation of OSSL ec public point from TPM public point.
706 *
707 * @param[in] group The definition of the used ec curve.
708 * @param[in] key The TPM public key.
709 * @param[out] The TPM's public point in OSSL format.
710 * @retval TSS2_RC_SUCCESS on success.
711 * @retval TSS2_ESYS_RC_GENERAL_FAILURE The internal crypto engine failed.
712 */
713 static TSS2_RC
tpm_pub_to_ossl_pub(EC_GROUP * group,TPM2B_PUBLIC * key,EC_POINT ** tpm_pub_key)714 tpm_pub_to_ossl_pub(EC_GROUP *group, TPM2B_PUBLIC *key, EC_POINT **tpm_pub_key)
715 {
716
717 TSS2_RC r = TSS2_RC_SUCCESS;
718 BIGNUM *bn_x = NULL;
719 BIGNUM *bn_y = NULL;
720
721 /* Create the big numbers for the coordinates of the point */
722 if (!(bn_x = BN_bin2bn(&key->publicArea.unique.ecc.x.buffer[0],
723 key->publicArea.unique.ecc.x.size,
724 NULL))) {
725 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
726 "Create big num from byte buffer.", cleanup);
727 }
728
729 if (!(bn_y = BN_bin2bn(&key->publicArea.unique.ecc.y.buffer[0],
730 key->publicArea.unique.ecc.y.size,
731 NULL))) {
732 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
733 "Create big num from byte buffer.", cleanup);
734 }
735
736 /* Create the ec point with the affine coordinates of the TPM point */
737 if (!(*tpm_pub_key = EC_POINT_new(group))) {
738 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
739 "Create point.", cleanup);
740 }
741
742 if (1 != EC_POINT_set_affine_coordinates_GFp(group,
743 *tpm_pub_key, bn_x,
744 bn_y, NULL)) {
745 OSSL_FREE(*tpm_pub_key, EC_POINT);
746 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
747 "Set affine coordinates", cleanup);
748 }
749
750 if (1 != EC_POINT_is_on_curve(group, *tpm_pub_key, NULL)) {
751 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
752 "The TPM point is not on the curve", cleanup);
753 }
754
755 cleanup:
756 OSSL_FREE(bn_x, BN);
757 OSSL_FREE(bn_y, BN);
758
759 return r;
760 }
761
762 /** Computation of ephemeral ECC key and shared secret Z.
763 *
764 * According to the description in TPM spec part 1 C 6.1 a shared secret
765 * between application and TPM is computed (ECDH). An ephemeral ECC key and a
766 * TPM keyare used for the ECDH key exchange.
767 * @param[in] key The key to be used for ECDH key exchange.
768 * @param[in] max_out_size the max size for the output of the public key of the
769 * computed ephemeral key.
770 * @param[out] Z The computed shared secret.
771 * @param[out] Q The public part of the ephemeral key in TPM format.
772 * @param[out] out_buffer The public part of the ephemeral key will be marshaled
773 * to this buffer.
774 * @param[out] out_size The size of the marshaled output.
775 * @retval TSS2_RC_SUCCESS on success
776 * @retval TSS2_ESYS_RC_BAD_VALUE The algorithm of key is not implemented.
777 * @retval TSS2_ESYS_RC_GENERAL_FAILURE The internal crypto engine failed.
778 */
779 TSS2_RC
iesys_cryptossl_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)780 iesys_cryptossl_get_ecdh_point(TPM2B_PUBLIC *key,
781 size_t max_out_size,
782 TPM2B_ECC_PARAMETER *Z,
783 TPMS_ECC_POINT *Q,
784 BYTE * out_buffer,
785 size_t * out_size)
786 {
787 TSS2_RC r = TSS2_RC_SUCCESS;
788 EC_GROUP *group = NULL; /* Group defines the used curve */
789 EC_KEY *eph_ec_key = NULL; /* Ephemeral ec key of application */
790 const EC_POINT *eph_pub_key = NULL; /* Public part of ephemeral key */
791 EC_POINT *tpm_pub_key = NULL; /* Public part of TPM key */
792 EC_POINT *mul_eph_tpm = NULL;
793 BIGNUM *bn_x = NULL;
794 BIGNUM *bn_y = NULL;
795 size_t key_size;
796 int curveId;
797 size_t offset;
798
799 /* Set ossl constant for curve type and create group for curve */
800 switch (key->publicArea.parameters.eccDetail.curveID) {
801 case TPM2_ECC_NIST_P192:
802 curveId = NID_X9_62_prime192v1;
803 key_size = 24;
804 break;
805 case TPM2_ECC_NIST_P224:
806 curveId = NID_secp224r1;
807 key_size = 28;
808 break;
809 case TPM2_ECC_NIST_P256:
810 curveId = NID_X9_62_prime256v1;
811 key_size = 32;
812 break;
813 case TPM2_ECC_NIST_P384:
814 curveId = NID_secp384r1;
815 key_size = 48;
816 break;
817 case TPM2_ECC_NIST_P521:
818 curveId = NID_secp521r1;
819 key_size = 66;
820 break;
821 default:
822 return_error(TSS2_ESYS_RC_NOT_IMPLEMENTED,
823 "ECC curve not implemented.");
824 }
825
826 if (!(group = EC_GROUP_new_by_curve_name(curveId))) {
827 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
828 "Create group for curve", cleanup);
829 }
830
831 /* Create ephemeral key */
832 if (!(eph_ec_key = EC_KEY_new())) {
833 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
834 "Create ec key", cleanup);
835 }
836 if (1 != EC_KEY_set_group(eph_ec_key , group)) {
837
838 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Set group", cleanup);
839 }
840
841 if (1 != EC_KEY_generate_key(eph_ec_key)) {
842 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Generate ec key", cleanup);
843 }
844
845 if (!(eph_pub_key = EC_KEY_get0_public_key(eph_ec_key))) {
846 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Get public key", cleanup);
847 }
848
849 if (1 != EC_POINT_is_on_curve(group, eph_pub_key, NULL)) {
850 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
851 "Ephemeral public key is on curve",cleanup);
852 }
853
854 /* Write affine coordinates of ephemeral pub key to TPM point Q */
855 if (!(bn_x = BN_new())) {
856 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Create bignum", cleanup);
857 }
858
859 if (!(bn_y = BN_new())) {
860 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Create bignum", cleanup);
861 }
862
863 if (1 != EC_POINT_get_affine_coordinates_GFp(group, eph_pub_key, bn_x,
864 bn_y, NULL)) {
865 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
866 "Get affine x coordinate", cleanup);
867 }
868
869 if (1 != iesys_bn2binpad(bn_x, &Q->x.buffer[0], key_size)) {
870 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
871 "Write big num byte buffer", cleanup);
872 }
873
874 if (1 != iesys_bn2binpad(bn_y, &Q->y.buffer[0], key_size)) {
875 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
876 "Write big num byte buffer", cleanup);
877 }
878
879 Q->x.size = key_size;
880 Q->y.size = key_size;
881
882 /* Create an OSSL EC point from the TPM public point */
883 r = tpm_pub_to_ossl_pub(group, key, &tpm_pub_key);
884 goto_if_error(r, "Convert TPM pub point to ossl pub point", cleanup);
885
886 /* Multiply the ephemeral private key with TPM public key */
887 const BIGNUM * eph_priv_key = EC_KEY_get0_private_key(eph_ec_key);
888
889 if (!(mul_eph_tpm = EC_POINT_new(group))) {
890 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Create point.", cleanup);
891 }
892
893 if (1 != EC_POINT_mul(group, mul_eph_tpm, NULL,
894 tpm_pub_key, eph_priv_key, NULL)) {
895 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
896 "ec point multiplication", cleanup);
897 }
898
899 /* Write the x-part of the affine coordinate to Z */
900 if (1 != EC_POINT_get_affine_coordinates_GFp(group, mul_eph_tpm, bn_x,
901 bn_y, NULL)) {
902 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
903 "Get affine x coordinate", cleanup);
904 }
905
906 if (1 != iesys_bn2binpad(bn_x, &Z->buffer[0], key_size)) {
907 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
908 "Write big num byte buffer", cleanup);
909 }
910
911 Z->size = key_size;
912
913 /* Write the public ephemeral key in TPM format to out buffer */
914 offset = 0;
915 r = Tss2_MU_TPMS_ECC_POINT_Marshal(Q, &out_buffer[0], max_out_size, &offset);
916 goto_if_error(r, "Error marshaling", cleanup);
917 *out_size = offset;
918
919 cleanup:
920 OSSL_FREE(mul_eph_tpm, EC_POINT);
921 OSSL_FREE(tpm_pub_key, EC_POINT);
922 OSSL_FREE(group,EC_GROUP);
923 OSSL_FREE(eph_ec_key, EC_KEY);
924 /* Note: free of eph_pub_key already done by free of eph_ec_key */
925 OSSL_FREE(bn_x, BN);
926 OSSL_FREE(bn_y, BN);
927 return r;
928 }
929
930 /** Encrypt data with AES.
931 *
932 * @param[in] key key used for AES.
933 * @param[in] tpm_sym_alg AES type in TSS2 notation (must be TPM2_ALG_AES).
934 * @param[in] key_bits Key size in bits.
935 * @param[in] tpm_mode Block cipher mode of opertion in TSS2 notation (CFB).
936 * For parameter encryption only CFB can be used.
937 * @param[in] blk_len Length Block length of AES.
938 * @param[in,out] buffer Data to be encrypted. The encrypted date will be stored
939 * in this buffer.
940 * @param[in] buffer_size size of data to be encrypted.
941 * @param[in] iv The initialization vector. The size is equal to blk_len.
942 * @retval TSS2_RC_SUCCESS on success, or TSS2_ESYS_RC_BAD_VALUE and
943 * @retval TSS2_ESYS_RC_BAD_REFERENCE for invalid parameters,
944 * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
945 */
946 TSS2_RC
iesys_cryptossl_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)947 iesys_cryptossl_sym_aes_encrypt(uint8_t * key,
948 TPM2_ALG_ID tpm_sym_alg,
949 TPMI_AES_KEY_BITS key_bits,
950 TPM2_ALG_ID tpm_mode,
951 size_t blk_len,
952 uint8_t * buffer,
953 size_t buffer_size,
954 uint8_t * iv)
955 {
956 TSS2_RC r = TSS2_RC_SUCCESS;
957 const EVP_CIPHER *cipher_alg = NULL;
958 EVP_CIPHER_CTX *ctx = NULL;
959 int cipher_len;
960
961 if (key == NULL || buffer == NULL) {
962 return_error(TSS2_ESYS_RC_BAD_REFERENCE, "Bad reference");
963 }
964
965 LOGBLOB_TRACE(buffer, buffer_size, "IESYS AES input");
966
967 /* Parameter blk_len needed for other crypto libraries */
968 (void)blk_len;
969
970 if (key_bits == 128 && tpm_mode == TPM2_ALG_CFB)
971 cipher_alg = EVP_aes_128_cfb();
972 else if (key_bits == 192 && tpm_mode == TPM2_ALG_CFB)
973 cipher_alg = EVP_aes_192_cfb();
974 else if (key_bits == 256 && tpm_mode == TPM2_ALG_CFB)
975 cipher_alg = EVP_aes_256_cfb();
976 else {
977 goto_error(r, TSS2_ESYS_RC_BAD_VALUE,
978 "AES algorithm not implemented or illegal mode (CFB expected).",
979 cleanup);
980 }
981
982 if (tpm_sym_alg != TPM2_ALG_AES) {
983 goto_error(r, TSS2_ESYS_RC_BAD_VALUE,
984 "AES encrypt called with wrong algorithm.", cleanup);
985 }
986
987 /* Create and initialize the context */
988 if(!(ctx = EVP_CIPHER_CTX_new())) {
989 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
990 "Initialize cipher context", cleanup);
991 }
992
993 if (1 != EVP_EncryptInit_ex(ctx, cipher_alg, NULL, key, iv)) {
994 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
995 "Initialize cipher operation", cleanup);
996 }
997 if (1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) {
998 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Set key and iv", cleanup);
999 }
1000
1001 /* Perform the encryption */
1002 if (1 != EVP_EncryptUpdate(ctx, buffer, &cipher_len, buffer, buffer_size)) {
1003 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Encrypt update", cleanup);
1004 }
1005
1006 if (1 != EVP_EncryptFinal_ex(ctx, buffer, &cipher_len)) {
1007 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Encrypt final", cleanup);
1008 }
1009 LOGBLOB_TRACE(buffer, buffer_size, "IESYS AES output");
1010
1011 cleanup:
1012
1013 OSSL_FREE(ctx,EVP_CIPHER_CTX);
1014
1015 return r;
1016 }
1017
1018 /** Decrypt data with AES.
1019 *
1020 * @param[in] key key used for AES.
1021 * @param[in] tpm_sym_alg AES type in TSS2 notation (must be TPM2_ALG_AES).
1022 * @param[in] key_bits Key size in bits.
1023 * @param[in] tpm_mode Block cipher mode of opertion in TSS2 notation (CFB).
1024 * For parameter encryption only CFB can be used.
1025 * @param[in] blk_len Length Block length of AES.
1026 * @param[in,out] buffer Data to be decrypted. The decrypted date will be stored
1027 * in this buffer.
1028 * @param[in] buffer_size size of data to be encrypted.
1029 * @param[in] iv The initialization vector. The size is equal to blk_len.
1030 * @retval TSS2_RC_SUCCESS on success, or TSS2_ESYS_RC_BAD_VALUE and
1031 * @retval TSS2_ESYS_RC_BAD_REFERENCE for invalid parameters,
1032 * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
1033 */
1034 TSS2_RC
iesys_cryptossl_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)1035 iesys_cryptossl_sym_aes_decrypt(uint8_t * key,
1036 TPM2_ALG_ID tpm_sym_alg,
1037 TPMI_AES_KEY_BITS key_bits,
1038 TPM2_ALG_ID tpm_mode,
1039 size_t blk_len,
1040 uint8_t * buffer,
1041 size_t buffer_size,
1042 uint8_t * iv)
1043 {
1044 TSS2_RC r = TSS2_RC_SUCCESS;
1045 const EVP_CIPHER *cipher_alg = NULL;
1046 EVP_CIPHER_CTX *ctx = NULL;
1047 int cipher_len = 0;
1048
1049 /* Parameter blk_len needed for other crypto libraries */
1050 (void)blk_len;
1051
1052 if (key == NULL || buffer == NULL) {
1053 return_error(TSS2_ESYS_RC_BAD_REFERENCE, "Bad reference");
1054 }
1055
1056 if (tpm_sym_alg != TPM2_ALG_AES) {
1057 goto_error(r, TSS2_ESYS_RC_BAD_VALUE,
1058 "AES encrypt called with wrong algorithm.", cleanup);
1059 }
1060
1061 if (key_bits == 128 && tpm_mode == TPM2_ALG_CFB)
1062 cipher_alg = EVP_aes_128_cfb();
1063 else if (key_bits == 192 && tpm_mode == TPM2_ALG_CFB)
1064 cipher_alg = EVP_aes_192_cfb();
1065 else if (key_bits == 256 && tpm_mode == TPM2_ALG_CFB)
1066 cipher_alg = EVP_aes_256_cfb();
1067 else {
1068
1069 goto_error(r, TSS2_ESYS_RC_NOT_IMPLEMENTED,
1070 "AES algorithm not implemented.", cleanup);
1071 }
1072
1073 /* Create and initialize the context */
1074 if(!(ctx = EVP_CIPHER_CTX_new())) {
1075 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
1076 "Initialize cipher context", cleanup);
1077 }
1078
1079 LOGBLOB_TRACE(buffer, buffer_size, "IESYS AES input");
1080
1081 if (1 != EVP_DecryptInit_ex(ctx, cipher_alg, NULL, key, iv)) {
1082 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
1083 "Initialize cipher operation", cleanup);
1084 }
1085
1086 if (1 != EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) {
1087 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Set key and iv", cleanup);
1088 }
1089
1090 /* Perform the decryption */
1091 if (1 != EVP_DecryptUpdate(ctx, buffer, &cipher_len, buffer, buffer_size)) {
1092 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Encrypt update", cleanup);
1093 }
1094
1095 if (1 != EVP_DecryptFinal_ex(ctx, buffer, &cipher_len)) {
1096 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Encrypt final", cleanup);
1097 }
1098 LOGBLOB_TRACE(buffer, buffer_size, "IESYS AES output");
1099
1100 cleanup:
1101
1102 OSSL_FREE(ctx,EVP_CIPHER_CTX);
1103 return r;
1104 }
1105
1106
1107 /** Initialize OpenSSL crypto backend.
1108 *
1109 * Initialize OpenSSL internal tables.
1110 *
1111 * @retval TSS2_RC_SUCCESS always returned because OpenSSL_add_all_algorithms
1112 * does not deliver
1113 * a return code.
1114 */
1115 TSS2_RC
iesys_cryptossl_init()1116 iesys_cryptossl_init() {
1117 ENGINE_load_builtin_engines();
1118 OpenSSL_add_all_algorithms();
1119 return TSS2_RC_SUCCESS;
1120 }
1121