xref: /aosp_15_r20/external/tpm2-tss/src/tss2-esys/esys_crypto_bssl.c (revision 758e9fba6fc9adbf15340f70c73baee7b168b1c9)
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