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