From f328c68cba9d5511b7d2d2615b3a28987edbdfac Mon Sep 17 00:00:00 2001 From: Petr Gotthard Date: Sun, 18 Jul 2021 21:30:59 +0200 Subject: Implement EVP_PKEY export/import for OpenSSL 3.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `RSA_KEY` and `EC_KEY` are not publicly available in OpenSSL 3.0 and the generic `EVP_PKEY` must be used instead. Since export/import of raw keys still requires access to the internal structures the OpenSSL 3.0 introduced a completely new approach to access key internals. This PR: - preserves the current export/import impementation for OpenSSL 1.1.x - implements key export/import for OpenSSL 3.0.0 Signed-off-by: Petr Gotthard --- src/tss2-esys/esys_crypto_ossl.c | 154 ++++++++++++----- src/tss2-fapi/fapi_crypto.c | 275 +++++++++++++++++++++---------- test/helper/tpm_getek.c | 53 +++--- test/helper/tpm_getek_ecc.c | 61 +++++-- 4 files changed, 386 insertions(+), 157 deletions(-) diff --git a/src/tss2-esys/esys_crypto_ossl.c b/src/tss2-esys/esys_crypto_ossl.c index a6259346..392f97ae 100644 --- a/src/tss2-esys/esys_crypto_ossl.c +++ b/src/tss2-esys/esys_crypto_ossl.c @@ -8,9 +8,17 @@ #include #endif +#include #include -#include #include +#include +#if OPENSSL_VERSION_NUMBER < 0x30000000L +#include +#else +#include +#include +#include +#endif #include #include @@ -324,9 +332,14 @@ iesys_cryptossl_hmac_start(IESYS_CRYPTO_CONTEXT_BLOB ** context, "Error EVP_MD_CTX_create", cleanup); } +#if OPENSSL_VERSION_NUMBER < 0x10101000L if (!(hkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, key, size))) { +#else + /* this is preferred, but available since OpenSSL 1.1.1 only */ + if (!(hkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, key, size))) { +#endif goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, - "EVP_PKEY_new_mac_key", cleanup); + "Failed to create HMAC key", cleanup); } if(1 != EVP_DigestSignInit(mycontext->hmac.ossl_context, NULL, @@ -517,7 +530,10 @@ iesys_cryptossl_hmac_abort(IESYS_CRYPTO_CONTEXT_BLOB ** context) TSS2_RC iesys_cryptossl_random2b(TPM2B_NONCE * nonce, size_t num_bytes) { +#if OPENSSL_VERSION_NUMBER < 0x30000000L const RAND_METHOD *rand_save = RAND_get_rand_method(); + RAND_set_rand_method(RAND_OpenSSL()); +#endif if (num_bytes == 0) { nonce->size = sizeof(TPMU_HA); @@ -525,13 +541,16 @@ iesys_cryptossl_random2b(TPM2B_NONCE * nonce, size_t num_bytes) nonce->size = num_bytes; } - RAND_set_rand_method(RAND_OpenSSL()); if (1 != RAND_bytes(&nonce->buffer[0], nonce->size)) { +#if OPENSSL_VERSION_NUMBER < 0x30000000L RAND_set_rand_method(rand_save); +#endif return_error(TSS2_ESYS_RC_GENERAL_FAILURE, "Failure in random number generator."); } +#if OPENSSL_VERSION_NUMBER < 0x30000000L RAND_set_rand_method(rand_save); +#endif return TSS2_RC_SUCCESS; } @@ -558,30 +577,33 @@ iesys_cryptossl_pk_encrypt(TPM2B_PUBLIC * pub_tpm_key, BYTE * out_buffer, size_t * out_size, const char *label) { +#if OPENSSL_VERSION_NUMBER < 0x30000000L + RSA *rsa_key = NULL; const RAND_METHOD *rand_save = RAND_get_rand_method(); + RAND_set_rand_method(RAND_OpenSSL()); +#else + OSSL_PARAM *params = NULL; + OSSL_PARAM_BLD *build = NULL; +#endif TSS2_RC r = TSS2_RC_SUCCESS; const EVP_MD * hashAlg = NULL; - RSA * rsa_key = NULL; EVP_PKEY *evp_rsa_key = NULL; - EVP_PKEY_CTX *ctx = NULL; - BIGNUM* bne = NULL; + EVP_PKEY_CTX *genctx = NULL, *ctx = NULL; + BIGNUM *bne = NULL, *n = NULL; int padding; char *label_copy = NULL; if (!(hashAlg = get_ossl_hash_md(pub_tpm_key->publicArea.nameAlg))) { LOG_ERROR("Unsupported hash algorithm (%"PRIu16")", pub_tpm_key->publicArea.nameAlg); +#if OPENSSL_VERSION_NUMBER < 0x30000000L RAND_set_rand_method(rand_save); +#endif return TSS2_ESYS_RC_NOT_IMPLEMENTED; } - if (!(bne = BN_new())) { - goto_error(r, TSS2_ESYS_RC_MEMORY, - "Could not allocate Big Number", cleanup); - } - switch (pub_tpm_key->publicArea.parameters.rsaDetail.scheme.scheme) { case TPM2_ALG_NULL: padding = RSA_NO_PADDING; @@ -601,44 +623,64 @@ iesys_cryptossl_pk_encrypt(TPM2B_PUBLIC * pub_tpm_key, exp = 65537; else exp = pub_tpm_key->publicArea.parameters.rsaDetail.exponent; - if (1 != BN_set_word(bne, exp)) { + + if (!(n = BN_bin2bn(pub_tpm_key->publicArea.unique.rsa.buffer, + pub_tpm_key->publicArea.unique.rsa.size, + NULL))) { goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, - "Could not set exponent.", cleanup); + "Could not create rsa n.", cleanup); } +#if OPENSSL_VERSION_NUMBER < 0x30000000L if (!(rsa_key = RSA_new())) { goto_error(r, TSS2_ESYS_RC_MEMORY, "Could not allocate RSA key", cleanup); } - if (1 != RSA_generate_key_ex(rsa_key, - pub_tpm_key->publicArea.parameters.rsaDetail.keyBits, - bne, NULL)) { - goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Could not generate RSA key", - cleanup); + if (!(bne = BN_new())) { + goto_error(r, TSS2_ESYS_RC_MEMORY, + "Could not allocate Big Number", cleanup); } - - if (!(evp_rsa_key = EVP_PKEY_new())) { + if (1 != BN_set_word(bne, exp)) { goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, - "Could not create evp key.", cleanup); + "Could not set exponent.", cleanup); } - BIGNUM *n = NULL; - if (!(n = BN_bin2bn(pub_tpm_key->publicArea.unique.rsa.buffer, - pub_tpm_key->publicArea.unique.rsa.size, - NULL))) { + + if (1 != RSA_set0_key(rsa_key, n, bne, NULL)) { goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, - "Could not create rsa n.", cleanup); + "Could not set rsa n.", cleanup); } + /* ownership got transferred */ + n = NULL; + bne = NULL; - if (1 != RSA_set0_key(rsa_key, n, NULL, NULL)) { + if (!(evp_rsa_key = EVP_PKEY_new())) { goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, - "Could not set rsa n.", cleanup); + "Could not create evp key.", cleanup); } - if (1 != EVP_PKEY_set1_RSA(evp_rsa_key, rsa_key)) { + if (1 != EVP_PKEY_assign_RSA(evp_rsa_key, rsa_key)) { goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Could not set rsa key.", cleanup); } + /* ownership got transferred */ + rsa_key = NULL; +#else /* OPENSSL_VERSION_NUMBER < 0x30000000L */ + if ((build = OSSL_PARAM_BLD_new()) == NULL + || !OSSL_PARAM_BLD_push_BN(build, OSSL_PKEY_PARAM_RSA_N, n) + || !OSSL_PARAM_BLD_push_uint32(build, OSSL_PKEY_PARAM_RSA_E, exp) + || (params = OSSL_PARAM_BLD_to_param(build)) == NULL) { + goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Could not create rsa parameters.", + cleanup); + } + + if ((genctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL)) == NULL + || EVP_PKEY_fromdata_init(genctx) <= 0 + || EVP_PKEY_fromdata(genctx, &evp_rsa_key, EVP_PKEY_PUBLIC_KEY, params) <= 0) { + goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Could not create rsa key.", + cleanup); + } +#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */ if (!(ctx = EVP_PKEY_CTX_new(evp_rsa_key, NULL))) { goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, @@ -692,11 +734,18 @@ iesys_cryptossl_pk_encrypt(TPM2B_PUBLIC * pub_tpm_key, r = TSS2_RC_SUCCESS; cleanup: + OSSL_FREE(genctx, EVP_PKEY_CTX); OSSL_FREE(ctx, EVP_PKEY_CTX); OSSL_FREE(evp_rsa_key, EVP_PKEY); - OSSL_FREE(rsa_key, RSA); OSSL_FREE(bne, BN); + OSSL_FREE(n, BN); +#if OPENSSL_VERSION_NUMBER < 0x30000000L + OSSL_FREE(rsa_key, RSA); RAND_set_rand_method(rand_save); +#else + OSSL_FREE(params, OSSL_PARAM); + OSSL_FREE(build, OSSL_PARAM_BLD); +#endif return r; } @@ -784,8 +833,14 @@ iesys_cryptossl_get_ecdh_point(TPM2B_PUBLIC *key, { TSS2_RC r = TSS2_RC_SUCCESS; EC_GROUP *group = NULL; /* Group defines the used curve */ - EC_KEY *eph_ec_key = NULL; /* Ephemeral ec key of application */ + EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *eph_pkey = NULL; +#if OPENSSL_VERSION_NUMBER < 0x30000000L const EC_POINT *eph_pub_key = NULL; /* Public part of ephemeral key */ + const BIGNUM *eph_priv_key = NULL; +#else + BIGNUM *eph_priv_key = NULL; +#endif EC_POINT *tpm_pub_key = NULL; /* Public part of TPM key */ EC_POINT *mul_eph_tpm = NULL; BIGNUM *bn_x = NULL; @@ -827,23 +882,25 @@ iesys_cryptossl_get_ecdh_point(TPM2B_PUBLIC *key, } /* Create ephemeral key */ - if (!(eph_ec_key = EC_KEY_new())) { + if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) == NULL + || EVP_PKEY_keygen_init(ctx) <= 0) { goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, - "Create ec key", cleanup); + "Initialize ec key generation", cleanup); } - if (1 != EC_KEY_set_group(eph_ec_key , group)) { - goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Set group", cleanup); - } - - if (1 != EC_KEY_generate_key(eph_ec_key)) { + if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, curveId) <= 0 + || EVP_PKEY_keygen(ctx, &eph_pkey) <= 0) { goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Generate ec key", cleanup); } +#if OPENSSL_VERSION_NUMBER < 0x30000000L + EC_KEY *eph_ec_key = EVP_PKEY_get0_EC_KEY(eph_pkey); + if (!(eph_pub_key = EC_KEY_get0_public_key(eph_ec_key))) { goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Get public key", cleanup); } + eph_priv_key = EC_KEY_get0_private_key(eph_ec_key); if (1 != EC_POINT_is_on_curve(group, eph_pub_key, NULL)) { goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Ephemeral public key is on curve",cleanup); @@ -861,8 +918,16 @@ iesys_cryptossl_get_ecdh_point(TPM2B_PUBLIC *key, if (1 != EC_POINT_get_affine_coordinates_tss(group, eph_pub_key, bn_x, bn_y, NULL)) { goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, - "Get affine x coordinate", cleanup); + "Get affine coordinates", cleanup); + } +#else + if (!EVP_PKEY_get_bn_param(eph_pkey, OSSL_PKEY_PARAM_PRIV_KEY, &eph_priv_key) + || !EVP_PKEY_get_bn_param(eph_pkey, OSSL_PKEY_PARAM_EC_PUB_X, &bn_x) + || !EVP_PKEY_get_bn_param(eph_pkey, OSSL_PKEY_PARAM_EC_PUB_Y, &bn_y)) { + goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, + "Get ephemeral key", cleanup); } +#endif if (1 != iesys_bn2binpad(bn_x, &Q->x.buffer[0], key_size)) { goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, @@ -881,13 +946,11 @@ iesys_cryptossl_get_ecdh_point(TPM2B_PUBLIC *key, r = tpm_pub_to_ossl_pub(group, key, &tpm_pub_key); goto_if_error(r, "Convert TPM pub point to ossl pub point", cleanup); - /* Multiply the ephemeral private key with TPM public key */ - const BIGNUM * eph_priv_key = EC_KEY_get0_private_key(eph_ec_key); - if (!(mul_eph_tpm = EC_POINT_new(group))) { goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Create point.", cleanup); } + /* Multiply the ephemeral private key with TPM public key */ if (1 != EC_POINT_mul(group, mul_eph_tpm, NULL, tpm_pub_key, eph_priv_key, NULL)) { goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, @@ -918,8 +981,13 @@ iesys_cryptossl_get_ecdh_point(TPM2B_PUBLIC *key, OSSL_FREE(mul_eph_tpm, EC_POINT); OSSL_FREE(tpm_pub_key, EC_POINT); OSSL_FREE(group,EC_GROUP); - OSSL_FREE(eph_ec_key, EC_KEY); + OSSL_FREE(ctx, EVP_PKEY_CTX); + OSSL_FREE(eph_pkey, EVP_PKEY); +#if OPENSSL_VERSION_NUMBER < 0x30000000L /* Note: free of eph_pub_key already done by free of eph_ec_key */ +#else + OSSL_FREE(eph_priv_key, BN); +#endif OSSL_FREE(bn_x, BN); OSSL_FREE(bn_y, BN); return r; diff --git a/src/tss2-fapi/fapi_crypto.c b/src/tss2-fapi/fapi_crypto.c index c97b0a1d..c50b5f0a 100644 --- a/src/tss2-fapi/fapi_crypto.c +++ b/src/tss2-fapi/fapi_crypto.c @@ -11,10 +11,15 @@ #include #include -#include #include -#include #include +#if OPENSSL_VERSION_NUMBER < 0x30000000L +#include +#else +#include +#include +#include +#endif #include #include #include @@ -380,66 +385,89 @@ cleanup: * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated. */ static TSS2_RC -ossl_rsa_pub_from_tpm(const TPM2B_PUBLIC *tpmPublicKey, EVP_PKEY *evpPublicKey) +ossl_rsa_pub_from_tpm(const TPM2B_PUBLIC *tpmPublicKey, EVP_PKEY **evpPublicKey) { +#if OPENSSL_VERSION_NUMBER < 0x30000000L + RSA *rsa = NULL; +#else + OSSL_PARAM_BLD *build = NULL; + OSSL_PARAM *params = NULL; + EVP_PKEY_CTX *ctx = NULL; +#endif + /* Check for NULL parameters */ return_if_null(tpmPublicKey, "tpmPublicKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE); return_if_null(evpPublicKey, "evpPublicKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE); + TSS2_RC r = TSS2_RC_SUCCESS; /* Initialize the RSA parameters */ - TSS2_RC r; - RSA *rsa = RSA_new(); - BIGNUM *e = BN_new(); - BIGNUM *d = BN_new(); - BIGNUM *p = BN_new(); - BIGNUM *q = BN_new(); - BIGNUM *dmp1 = BN_new(); - BIGNUM *dmq1 = BN_new(); - BIGNUM *iqmp = BN_new(); + BIGNUM *e = NULL; BIGNUM *n = BN_bin2bn(tpmPublicKey->publicArea.unique.rsa.buffer, tpmPublicKey->publicArea.unique.rsa.size, NULL); - - if (!n || !e || !d || !p || !q || !dmp1 || !dmq1 || !iqmp || !rsa) { + if (!n) { goto_error(r, TSS2_FAPI_RC_MEMORY, "Out of memory", error_cleanup); } - BN_set_word(d, 0); - BN_set_word(p, 0); - BN_set_word(q, 0); - BN_set_word(dmp1, 0); - BN_set_word(dmq1, 0); - BN_set_word(iqmp, 0); uint32_t exp; if (tpmPublicKey->publicArea.parameters.rsaDetail.exponent == 0) exp = 65537; else exp = tpmPublicKey->publicArea.parameters.rsaDetail.exponent; + +#if OPENSSL_VERSION_NUMBER < 0x30000000L + if ((rsa = RSA_new()) == NULL) { + goto_error(r, TSS2_FAPI_RC_MEMORY, "Out of memory", error_cleanup); + } + + if ((e = BN_new()) == NULL) { + goto_error(r, TSS2_FAPI_RC_MEMORY, "Out of memory", error_cleanup); + } if (1 != BN_set_word(e, exp)) { goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Could not set exponent.", error_cleanup); } - RSA_set0_key(rsa, n, e, d); - RSA_set0_factors(rsa, p, q); - RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp); + if (!RSA_set0_key(rsa, n, e, NULL)) { + goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, + "Could not set public key.", error_cleanup); + } + n = NULL; /* ownership transferred */ + e = NULL; + + *evpPublicKey = EVP_PKEY_new(); + goto_if_null2(*evpPublicKey, "Out of memory.", r, TSS2_FAPI_RC_MEMORY, error_cleanup); /* Assign the parameters to the key */ - if (!EVP_PKEY_assign_RSA(evpPublicKey, rsa)) { + if (!EVP_PKEY_assign_RSA(*evpPublicKey, rsa)) { + EVP_PKEY_free(*evpPublicKey); goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Assign rsa key", error_cleanup); } - return TSS2_RC_SUCCESS; - + rsa = NULL; /* ownership transferred */ error_cleanup: OSSL_FREE(rsa, RSA); +#else /* OPENSSL_VERSION_NUMBER < 0x30000000L */ + if ((build = OSSL_PARAM_BLD_new()) == NULL + || !OSSL_PARAM_BLD_push_BN(build, OSSL_PKEY_PARAM_RSA_N, n) + || !OSSL_PARAM_BLD_push_uint32(build, OSSL_PKEY_PARAM_RSA_E, exp) + || (params = OSSL_PARAM_BLD_to_param(build)) == NULL) { + goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Create rsa key parameters", + error_cleanup); + } + + if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL)) == NULL + || EVP_PKEY_fromdata_init(ctx) <= 0 + || EVP_PKEY_fromdata(ctx, evpPublicKey, EVP_PKEY_PUBLIC_KEY, params) <= 0) { + goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Create rsa key", + error_cleanup); + } +error_cleanup: + OSSL_FREE(ctx, EVP_PKEY_CTX); + OSSL_FREE(params, OSSL_PARAM); + OSSL_FREE(build, OSSL_PARAM_BLD); +#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */ OSSL_FREE(e, BN); OSSL_FREE(n, BN); - OSSL_FREE(d, BN); - OSSL_FREE(p, BN); - OSSL_FREE(q, BN); - OSSL_FREE(dmp1, BN); - OSSL_FREE(dmq1, BN); - OSSL_FREE(iqmp, BN); return r; } @@ -459,18 +487,26 @@ error_cleanup: * the function. */ static TSS2_RC -ossl_ecc_pub_from_tpm(const TPM2B_PUBLIC *tpmPublicKey, EVP_PKEY *evpPublicKey) +ossl_ecc_pub_from_tpm(const TPM2B_PUBLIC *tpmPublicKey, EVP_PKEY **evpPublicKey) { /* Check for NULL parameters */ return_if_null(tpmPublicKey, "tpmPublicKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE); return_if_null(evpPublicKey, "evpPublicKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE); - TSS2_RC r; + TSS2_RC r = TSS2_RC_SUCCESS; EC_GROUP *ecgroup = NULL; int curveId; BIGNUM *x = NULL, *y = NULL; - EC_KEY *ecKey = EC_KEY_new(); - return_if_null(ecKey, "Out of memory.", TSS2_FAPI_RC_MEMORY); + EC_POINT *ecPoint = NULL; +#if OPENSSL_VERSION_NUMBER < 0x30000000L + EC_KEY *ecKey = NULL; +#else + OSSL_PARAM_BLD *build = NULL; + OSSL_PARAM *params = NULL; + EVP_PKEY_CTX *ctx = NULL; + unsigned char *puboct = NULL; + size_t bsize; +#endif /* Find the curve of the ECC key */ switch (tpmPublicKey->publicArea.parameters.eccDetail.curveID) { @@ -499,12 +535,6 @@ ossl_ecc_pub_from_tpm(const TPM2B_PUBLIC *tpmPublicKey, EVP_PKEY *evpPublicKey) goto_if_null(ecgroup, "new EC group.", TSS2_FAPI_RC_GENERAL_FAILURE, error_cleanup); - if (!EC_KEY_set_group(ecKey, ecgroup)) { - goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "EC_KEY_set_group", - error_cleanup); - } - EC_GROUP_free(ecgroup); - /* Set the ECC parameters in the OpenSSL key */ x = BN_bin2bn(tpmPublicKey->publicArea.unique.ecc.x.buffer, tpmPublicKey->publicArea.unique.ecc.x.size, NULL); @@ -516,23 +546,67 @@ ossl_ecc_pub_from_tpm(const TPM2B_PUBLIC *tpmPublicKey, EVP_PKEY *evpPublicKey) goto_error(r, TSS2_FAPI_RC_MEMORY, "Out of memory", error_cleanup); } - if (!EC_KEY_set_public_key_affine_coordinates(ecKey, x, y)) { + if ((ecPoint = EC_POINT_new(ecgroup)) == NULL + || !EC_POINT_set_affine_coordinates_tss(ecgroup, ecPoint, x, y, NULL)) { + goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "EC_POINT_set_affine_coordinates", + error_cleanup); + } + +#if OPENSSL_VERSION_NUMBER < 0x30000000 + ecKey = EC_KEY_new(); + return_if_null(ecKey, "Out of memory.", TSS2_FAPI_RC_MEMORY); + + if (!EC_KEY_set_group(ecKey, ecgroup)) { + goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "EC_KEY_set_group", + error_cleanup); + } + + if (!EC_KEY_set_public_key(ecKey, ecPoint)) { goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, - "EC_KEY_set_public_key_affine_coordinates", error_cleanup); + "EC_KEY_set_public_key", error_cleanup); } - if (!EVP_PKEY_assign_EC_KEY(evpPublicKey, ecKey)) { + *evpPublicKey = EVP_PKEY_new(); + goto_if_null2(*evpPublicKey, "Out of memory.", r, TSS2_FAPI_RC_MEMORY, error_cleanup); + + if (!EVP_PKEY_assign_EC_KEY(*evpPublicKey, ecKey)) { + EVP_PKEY_free(*evpPublicKey); goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Assign ecc key", error_cleanup); } - OSSL_FREE(y, BN); - OSSL_FREE(x, BN); - return TSS2_RC_SUCCESS; + ecKey = NULL; /* ownership transferred */ +error_cleanup: + OSSL_FREE(ecKey, EC_KEY); +#else + if ((build = OSSL_PARAM_BLD_new()) == NULL + || !OSSL_PARAM_BLD_push_utf8_string(build, OSSL_PKEY_PARAM_GROUP_NAME, + (char *)OBJ_nid2sn(curveId), 0) + || (bsize = EC_POINT_point2buf(ecgroup, ecPoint, + POINT_CONVERSION_COMPRESSED, + &puboct, NULL)) == 0 + || !OSSL_PARAM_BLD_push_octet_string(build, OSSL_PKEY_PARAM_PUB_KEY, + puboct, bsize) + || (params = OSSL_PARAM_BLD_to_param(build)) == NULL) { + goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Create ecc key parameters", + error_cleanup); + } + if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)) == NULL + || EVP_PKEY_fromdata_init(ctx) <= 0 + || EVP_PKEY_fromdata(ctx, evpPublicKey, EVP_PKEY_PUBLIC_KEY, params) <= 0) { + goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Create ecc key", + error_cleanup); + } error_cleanup: + EVP_PKEY_CTX_free(ctx); + OSSL_PARAM_free(params); + OSSL_PARAM_BLD_free(build); + OPENSSL_free(puboct); +#endif + OSSL_FREE(ecPoint, EC_POINT); + OSSL_FREE(ecgroup, EC_GROUP); OSSL_FREE(y, BN); OSSL_FREE(x, BN); - OSSL_FREE(ecKey, EC_KEY); return r; } @@ -567,18 +641,15 @@ ifapi_pub_pem_key_from_tpm( BIO *bio = NULL; TSS2_RC r = TPM2_RC_SUCCESS; - evpPublicKey = EVP_PKEY_new(); - goto_if_null2(evpPublicKey, "Out of memory.", r, TSS2_FAPI_RC_MEMORY, cleanup); - /* Memory IO will be used for OSSL key conversion */ bio = BIO_new(BIO_s_mem()); - goto_if_null2(evpPublicKey, "Out of memory.", r, TSS2_FAPI_RC_MEMORY, cleanup); + goto_if_null2(bio, "Out of memory.", r, TSS2_FAPI_RC_MEMORY, cleanup); if (tpmPublicKey->publicArea.type == TPM2_ALG_RSA) { - r = ossl_rsa_pub_from_tpm(tpmPublicKey, evpPublicKey); - } else if (tpmPublicKey->publicArea.type == TPM2_ALG_ECC) - r = ossl_ecc_pub_from_tpm(tpmPublicKey, evpPublicKey); - else { + r = ossl_rsa_pub_from_tpm(tpmPublicKey, &evpPublicKey); + } else if (tpmPublicKey->publicArea.type == TPM2_ALG_ECC) { + r = ossl_ecc_pub_from_tpm(tpmPublicKey, &evpPublicKey); + } else { goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Invalid alg id.", cleanup); } goto_if_error(r, "Get ossl public key.", cleanup); @@ -708,7 +779,6 @@ ifapi_der_sig_to_tpm( signatureSize); } else { return_error(TSS2_FAPI_RC_BAD_VALUE, "Invalid RSA scheme."); - } } else if (tpmPublic->type == TPM2_ALG_ECC) { return ifapi_ecc_der_sig_to_tpm(signature, signatureSize, @@ -856,12 +926,16 @@ ecdsa_verify_signature( return_if_null(digest, "digest is NULL", TSS2_FAPI_RC_BAD_REFERENCE); TSS2_RC r = TSS2_RC_SUCCESS; - EC_KEY *eccKey = NULL; + EVP_PKEY_CTX *ctx = NULL; - eccKey = EVP_PKEY_get1_EC_KEY(publicKey); + if ((ctx = EVP_PKEY_CTX_new(publicKey, NULL)) == NULL + || !EVP_PKEY_verify_init(ctx)) { + goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, + "Cannot initialize signature verification.", error_cleanup); + } /* Try to verify the signature using ECDSA, note that param 0 is unused */ - int rc = ECDSA_verify(0, digest, digestSize, signature, signatureSize, eccKey); + int rc = EVP_PKEY_verify(ctx, signature, signatureSize, digest, digestSize); if (rc == 0) { goto_error(r, TSS2_FAPI_RC_SIGNATURE_VERIFICATION_FAILED, "ECDSA signature verification failed.", error_cleanup); @@ -871,7 +945,7 @@ ecdsa_verify_signature( } error_cleanup: - OSSL_FREE(eccKey, EC_KEY); + OSSL_FREE(ctx, EVP_PKEY_CTX); return r; } @@ -900,23 +974,43 @@ get_rsa_tpm2b_public_from_evp( /* Extract the public information */ TSS2_RC r = TSS2_RC_SUCCESS; + int keyBits, keySize; + +#if OPENSSL_VERSION_NUMBER < 0x30000000L + const BIGNUM *e = NULL, *n = NULL; RSA *rsaKey = EVP_PKEY_get1_RSA(publicKey); return_if_null(rsaKey, "Out of memory.", TSS2_FAPI_RC_MEMORY); - const BIGNUM *e = NULL, *n = NULL; - int rsaKeySize = RSA_size(rsaKey); + keySize = RSA_size(rsaKey); + keyBits = keySize * 8; RSA_get0_key(rsaKey, &n, &e, NULL); - tpmPublic->publicArea.unique.rsa.size = rsaKeySize; +#else + BIGNUM *e = NULL, *n = NULL; + + keyBits = EVP_PKEY_get_bits(publicKey); + keySize = (keyBits + 7) / 8; + if (!EVP_PKEY_get_bn_param(publicKey, OSSL_PKEY_PARAM_RSA_N, &n) + || !EVP_PKEY_get_bn_param(publicKey, OSSL_PKEY_PARAM_RSA_E, &e)) { + goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, + "Retrieve pubkey", cleanup); + } +#endif + tpmPublic->publicArea.unique.rsa.size = keySize; if (1 != ifapi_bn2binpad(n, &tpmPublic->publicArea.unique.rsa.buffer[0], - rsaKeySize)) { + keySize)) { goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Write big num byte buffer", cleanup); } - tpmPublic->publicArea.parameters.rsaDetail.keyBits = rsaKeySize * 8; + tpmPublic->publicArea.parameters.rsaDetail.keyBits = keyBits; tpmPublic->publicArea.parameters.rsaDetail.exponent = BN_get_word(e); cleanup: +#if OPENSSL_VERSION_NUMBER < 0x30000000L OSSL_FREE(rsaKey, RSA); +#else + BN_free(e); + BN_free(n); +#endif return r; } @@ -947,27 +1041,22 @@ get_ecc_tpm2b_public_from_evp( /* Initialize variables that will contain the relevant information */ TSS2_RC r = TSS2_RC_SUCCESS; - EC_KEY *ecKey = EVP_PKEY_get1_EC_KEY(publicKey); - return_if_null(ecKey, "Out of memory.", TSS2_FAPI_RC_MEMORY); - const EC_GROUP *ecGroup; - const EC_POINT *publicPoint; int curveId; size_t ecKeySize; BIGNUM *bnX = NULL; BIGNUM *bnY = NULL; TPMI_ECC_CURVE tpmCurveId; - - if (!ecKey) { - return_error(TSS2_FAPI_RC_GENERAL_FAILURE, "No ECC key!"); - } +#if OPENSSL_VERSION_NUMBER < 0x30000000 + const EC_GROUP *ecGroup; + const EC_POINT *publicPoint; + EC_KEY *ecKey = EVP_PKEY_get1_EC_KEY(publicKey); + return_if_null(ecKey, "Out of memory.", TSS2_FAPI_RC_MEMORY); /* Retrieve the relevant information and write it to tpmPublic */ ecGroup = EC_KEY_get0_group(ecKey); publicPoint = EC_KEY_get0_public_key(ecKey); curveId = EC_GROUP_get_curve_name(ecGroup); - ecKeySize = EC_GROUP_get_degree(ecGroup) / 8; - tpmPublic->publicArea.unique.ecc.x.size = ecKeySize; - tpmPublic->publicArea.unique.ecc.y.size = ecKeySize; + ecKeySize = (EC_GROUP_get_degree(ecGroup) + 7) / 8; if (!(bnX = BN_new())) { goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Create bignum", cleanup); @@ -982,6 +1071,23 @@ get_ecc_tpm2b_public_from_evp( goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Get affine coordinates", cleanup); } +#else + char curveName[80]; + + if (!EVP_PKEY_get_utf8_string_param(publicKey, OSSL_PKEY_PARAM_GROUP_NAME, + curveName, sizeof(curveName), NULL) + || !EVP_PKEY_get_bn_param(publicKey, OSSL_PKEY_PARAM_EC_PUB_X, &bnX) + || !EVP_PKEY_get_bn_param(publicKey, OSSL_PKEY_PARAM_EC_PUB_Y, &bnY)) { + goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, + "Get public key", cleanup); + } + curveId = OBJ_txt2nid(curveName); + EC_GROUP *ecGroup = EC_GROUP_new_by_curve_name(curveId); + ecKeySize = (EC_GROUP_get_degree(ecGroup) + 7) / 8; + EC_GROUP_free(ecGroup); +#endif + tpmPublic->publicArea.unique.ecc.x.size = ecKeySize; + tpmPublic->publicArea.unique.ecc.y.size = ecKeySize; if (1 != ifapi_bn2binpad(bnX, &tpmPublic->publicArea.unique.ecc.x.buffer[0], ecKeySize)) { goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, @@ -1015,7 +1121,9 @@ get_ecc_tpm2b_public_from_evp( tpmPublic->publicArea.parameters.eccDetail.curveID = tpmCurveId; cleanup: +#if OPENSSL_VERSION_NUMBER < 0x30000000 OSSL_FREE(ecKey, EC_KEY); +#endif OSSL_FREE(bnX, BN); OSSL_FREE(bnY, BN); return r; @@ -2077,14 +2185,11 @@ ifapi_get_tpm_key_fingerprint( "Unsupported hash algorithm (%" PRIu16 ")", cleanup, hashAlg); - evpPublicKey = EVP_PKEY_new(); - goto_if_null2(evpPublicKey, "Out of memory.", r, TSS2_FAPI_RC_MEMORY, cleanup); - if (tpmPublicKey->publicArea.type == TPM2_ALG_RSA) { - r = ossl_rsa_pub_from_tpm(tpmPublicKey, evpPublicKey); - } else if (tpmPublicKey->publicArea.type == TPM2_ALG_ECC) - r = ossl_ecc_pub_from_tpm(tpmPublicKey, evpPublicKey); - else { + r = ossl_rsa_pub_from_tpm(tpmPublicKey, &evpPublicKey); + } else if (tpmPublicKey->publicArea.type == TPM2_ALG_ECC) { + r = ossl_ecc_pub_from_tpm(tpmPublicKey, &evpPublicKey); + } else { goto_error(r,TSS2_FAPI_RC_BAD_VALUE, "Invalid alg id.", cleanup); } goto_if_error(r, "Get ossl public key.", cleanup); diff --git a/test/helper/tpm_getek.c b/test/helper/tpm_getek.c index c6a8e906..67f76b6a 100644 --- a/test/helper/tpm_getek.c +++ b/test/helper/tpm_getek.c @@ -7,8 +7,14 @@ #include #include #include -#include #include +#if OPENSSL_VERSION_NUMBER < 0x30000000 +#include +#else +#include +#include +#include +#endif #include "tss2_sys.h" #include "tss2_mu.h" @@ -109,7 +115,7 @@ main (int argc, char *argv[]) /* Convert the key from out_public to PEM */ - EVP_PKEY *evp = EVP_PKEY_new(); + EVP_PKEY *evp = NULL; BIO *bio; FILE *out = NULL; @@ -124,34 +130,35 @@ main (int argc, char *argv[]) else bio = BIO_new_fp(stdout, BIO_NOCLOSE); - RSA *rsa = RSA_new(); - BIGNUM *e = BN_new(); - BIGNUM *d = BN_new(); - BIGNUM *p = BN_new(); - BIGNUM *q = BN_new(); - BIGNUM *dmp1 = BN_new(); - BIGNUM *dmq1 = BN_new(); - BIGNUM *iqmp = BN_new(); BIGNUM *n = BN_bin2bn(out_public.publicArea.unique.rsa.buffer, out_public.publicArea.unique.rsa.size, NULL); - BN_set_word(d, 0); - BN_set_word(p, 0); - BN_set_word(q, 0); - BN_set_word(dmp1, 0); - BN_set_word(dmq1, 0); - BN_set_word(iqmp, 0); uint32_t exp; if (out_public.publicArea.parameters.rsaDetail.exponent == 0) exp = 65537; else exp = out_public.publicArea.parameters.rsaDetail.exponent; + +#if OPENSSL_VERSION_NUMBER < 0x30000000 + BIGNUM *e = BN_new(); BN_set_word(e, exp); - RSA_set0_key(rsa, n, e, d); - RSA_set0_factors(rsa, p, q); - RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp); + RSA *rsa = RSA_new(); + RSA_set0_key(rsa, n, e, NULL); + n = NULL; + e = NULL; + evp = EVP_PKEY_new(); EVP_PKEY_assign_RSA(evp, rsa); +#else /* OPENSSL_VERSION_NUMBER < 0x30000000 */ + OSSL_PARAM_BLD *build = OSSL_PARAM_BLD_new(); + OSSL_PARAM_BLD_push_BN(build, OSSL_PKEY_PARAM_RSA_N, n); + OSSL_PARAM_BLD_push_uint32(build, OSSL_PKEY_PARAM_RSA_E, exp); + OSSL_PARAM *params = OSSL_PARAM_BLD_to_param(build); + + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); + EVP_PKEY_fromdata_init(ctx); + EVP_PKEY_fromdata(ctx, &evp, EVP_PKEY_PUBLIC_KEY, params); +#endif /* OPENSSL_VERSION_NUMBER < 0x30000000 */ if (!PEM_write_bio_PUBKEY(bio, evp)) { LOG_ERROR("PEM_write failed"); @@ -159,6 +166,14 @@ main (int argc, char *argv[]) } EVP_PKEY_free(evp); +#if OPENSSL_VERSION_NUMBER < 0x30000000 + /* ownership was taken by the EVP_PKEY */ +#else + EVP_PKEY_CTX_free(ctx); + OSSL_PARAM_free(params); + OSSL_PARAM_BLD_free(build); +#endif + BN_free(n); BIO_free(bio); fclose(out); diff --git a/test/helper/tpm_getek_ecc.c b/test/helper/tpm_getek_ecc.c index 75165fdd..d4602925 100644 --- a/test/helper/tpm_getek_ecc.c +++ b/test/helper/tpm_getek_ecc.c @@ -7,9 +7,15 @@ #include #include #include -#include #include #include +#if OPENSSL_VERSION_NUMBER < 0x30000000 +#include +#else +#include +#include +#include +#endif #include #include "tss2_sys.h" @@ -127,8 +133,7 @@ main (int argc, char *argv[]) /* Convert the key from out_public to PEM */ - EVP_PKEY *evp = EVP_PKEY_new(); - EC_KEY *ecc_key = EC_KEY_new(); + EVP_PKEY *evp = NULL; BIGNUM *x = NULL, *y = NULL; BIO *bio; FILE *out = NULL; @@ -148,11 +153,6 @@ main (int argc, char *argv[]) nid = EC_curve_nist2nid("P-256"); EC_GROUP *ecgroup = EC_GROUP_new_by_curve_name(nid); - if (!EC_KEY_set_group(ecc_key, ecgroup)) - exit(1); - - EC_GROUP_free(ecgroup); - /* Set the ECC parameters in the OpenSSL key */ x = BN_bin2bn(out_public.publicArea.unique.ecc.x.buffer, out_public.publicArea.unique.ecc.x.size, NULL); @@ -164,15 +164,46 @@ main (int argc, char *argv[]) exit(1); } - if (!EC_KEY_set_public_key_affine_coordinates(ecc_key, x, y)) { + EC_POINT *point = EC_POINT_new(ecgroup); +#if OPENSSL_VERSION_NUMBER < 0x10101000L + EC_POINT_set_affine_coordinates_GFp(ecgroup, point, x, y, NULL); +#else + EC_POINT_set_affine_coordinates(ecgroup, point, x, y, NULL); +#endif + +#if OPENSSL_VERSION_NUMBER < 0x30000000 + EC_KEY *ecc_key = EC_KEY_new(); + if (!EC_KEY_set_group(ecc_key, ecgroup)) + exit(1); + + if (!EC_KEY_set_public_key(ecc_key, point)) { exit(1); } + evp = EVP_PKEY_new(); if (!EVP_PKEY_assign_EC_KEY(evp, ecc_key)) { handleErrors(); LOG_ERROR("PEM_write failed"); exit(1); } +#else /* OPENSSL_VERSION_NUMBER < 0x30000000 */ + unsigned char *puboct = NULL; + size_t bsize; + + bsize = EC_POINT_point2buf(ecgroup, point, POINT_CONVERSION_UNCOMPRESSED, + &puboct, NULL); + + OSSL_PARAM_BLD *build = OSSL_PARAM_BLD_new(); + OSSL_PARAM_BLD_push_utf8_string(build, OSSL_PKEY_PARAM_GROUP_NAME, + (char *)OBJ_nid2sn(nid), 0); + OSSL_PARAM_BLD_push_octet_string(build, OSSL_PKEY_PARAM_PUB_KEY, + puboct, bsize); + OSSL_PARAM *params = OSSL_PARAM_BLD_to_param(build); + + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); + EVP_PKEY_fromdata_init(ctx); + EVP_PKEY_fromdata(ctx, &evp, EVP_PKEY_PUBLIC_KEY, params); +#endif /* OPENSSL_VERSION_NUMBER < 0x30000000 */ if (!PEM_write_bio_PUBKEY(bio, evp)) { handleErrors(); @@ -180,9 +211,19 @@ main (int argc, char *argv[]) exit(1); } + EVP_PKEY_free(evp); +#if OPENSSL_VERSION_NUMBER < 0x30000000 + /* ownership was taken by the EVP_PKEY */ +#else + EVP_PKEY_CTX_free(ctx); + OSSL_PARAM_free(params); + OSSL_PARAM_BLD_free(build); + OPENSSL_free(puboct); +#endif + EC_POINT_free(point); + EC_GROUP_free(ecgroup); BN_free(y); BN_free(x); - EVP_PKEY_free(evp); BIO_free(bio); fclose(out); -- 2.26.3