Coverage Report

Created: 2026-05-16 06:23

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