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