From 6dc8c6a8df2c9569b78b218913fe6e9dc27b9e1a Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Sat, 7 Sep 2024 12:51:08 +0200 Subject: [PATCH] cert util: replace deprecated OpenSSL calls In OpenSSL 3.0 some of the calls we currently use in the utility functions to covert the public key from a X.509 certificate into an ssh public key got deprecated. This patch replaces them if OpenSSL 3.0 or newer is used. In contrast to the older calls which just returned references the new calls return the requested data in freshly allocated memory. To keep it consistent the data referenced by the old calls are copied into allocated memory as well. Resolves: https://github.com/SSSD/sssd/issues/5861 --- src/util/cert/libcrypto/cert.c | 185 +++++++++++++++++++++++++++++---- 1 file changed, 162 insertions(+), 23 deletions(-) diff --git a/src/util/cert/libcrypto/cert.c b/src/util/cert/libcrypto/cert.c index 61908c7f048..eda1cfb56e2 100644 --- a/src/util/cert/libcrypto/cert.c +++ b/src/util/cert/libcrypto/cert.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "util/util.h" #include "util/sss_endian.h" @@ -176,6 +177,95 @@ errno_t sss_cert_pem_to_der(TALLOC_CTX *mem_ctx, const char *pem, #define IDENTIFIER_NISTP384 "nistp384" #define IDENTIFIER_NISTP521 "nistp521" +static int sss_ec_get_key(BN_CTX *bn_ctx, EVP_PKEY *cert_pub_key, + EC_GROUP **ec_group, EC_POINT **ec_public_key) +{ +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + int ret; + char curve_name[4096]; + unsigned char pubkey[4096]; + size_t len; + EC_GROUP *gr; + EC_POINT *pk; + + ret = EVP_PKEY_get_utf8_string_param(cert_pub_key, + OSSL_PKEY_PARAM_GROUP_NAME, + curve_name, sizeof(curve_name), &len); + if (ret != 1) { + ret = EINVAL; + goto done; + } + + gr = EC_GROUP_new_by_curve_name(OBJ_sn2nid(curve_name)); + if (gr == NULL) { + ret = EINVAL; + goto done; + } + + ret = EVP_PKEY_get_octet_string_param(cert_pub_key, + OSSL_PKEY_PARAM_PUB_KEY, + pubkey, sizeof(pubkey), &len); + if (ret != 1) { + EC_GROUP_free(gr); + ret = EINVAL; + goto done; + } + + pk = EC_POINT_new(gr); + if (pk == NULL) { + EC_GROUP_free(gr); + ret = EINVAL; + goto done; + } + + ret = EC_POINT_oct2point(gr, pk, pubkey, len, bn_ctx); + if (ret != 1) { + EC_GROUP_free(gr); + EC_POINT_free(pk); + ret = EINVAL; + goto done; + } + + *ec_group = gr; + *ec_public_key = pk; + +#else + EC_KEY *ec_key = NULL; + const EC_GROUP *gr; + const EC_POINT *pk; + + ec_key = EVP_PKEY_get1_EC_KEY(cert_pub_key); + if (ec_key == NULL) { + ret = ENOMEM; + goto done; + } + + gr = EC_KEY_get0_group(ec_key); + + pk = EC_KEY_get0_public_key(ec_key); + + *ec_group = EC_GROUP_dup(gr); + if (*ec_group == NULL) { + EC_KEY_free(ec_key); + ret = ENOMEM; + goto done; + } + + *ec_public_key = EC_POINT_dup(pk, gr); + EC_KEY_free(ec_key); + if (*ec_public_key == NULL) { + EC_GROUP_free(*ec_group); + ret = ENOMEM; + goto done; + } +#endif + + ret = EOK; + +done: + return ret; +} + static errno_t ec_pub_key_to_ssh(TALLOC_CTX *mem_ctx, EVP_PKEY *cert_pub_key, uint8_t **key_blob, size_t *key_size) { @@ -183,9 +273,8 @@ static errno_t ec_pub_key_to_ssh(TALLOC_CTX *mem_ctx, EVP_PKEY *cert_pub_key, size_t c; uint8_t *buf = NULL; size_t buf_len; - EC_KEY *ec_key = NULL; - const EC_GROUP *ec_group = NULL; - const EC_POINT *ec_public_key = NULL; + EC_GROUP *ec_group = NULL; + EC_POINT *ec_public_key = NULL; BN_CTX *bn_ctx = NULL; int key_len; const char *identifier = NULL; @@ -193,14 +282,11 @@ static errno_t ec_pub_key_to_ssh(TALLOC_CTX *mem_ctx, EVP_PKEY *cert_pub_key, const char *header = NULL; int header_len; - ec_key = EVP_PKEY_get1_EC_KEY(cert_pub_key); - if (ec_key == NULL) { - ret = ENOMEM; + ret = sss_ec_get_key(bn_ctx, cert_pub_key, &ec_group, &ec_public_key); + if (ret != EOK) { goto done; } - ec_group = EC_KEY_get0_group(ec_key); - switch(EC_GROUP_get_curve_name(ec_group)) { case NID_X9_62_prime256v1: identifier = IDENTIFIER_NISTP256; @@ -224,8 +310,6 @@ static errno_t ec_pub_key_to_ssh(TALLOC_CTX *mem_ctx, EVP_PKEY *cert_pub_key, header_len = strlen(header); identifier_len = strlen(identifier); - ec_public_key = EC_KEY_get0_public_key(ec_key); - bn_ctx = BN_CTX_new(); if (bn_ctx == NULL) { DEBUG(SSSDBG_OP_FAILURE, "BN_CTX_new failed.\n"); @@ -279,7 +363,8 @@ static errno_t ec_pub_key_to_ssh(TALLOC_CTX *mem_ctx, EVP_PKEY *cert_pub_key, } BN_CTX_free(bn_ctx); - EC_KEY_free(ec_key); + EC_GROUP_free(ec_group); + EC_POINT_free(ec_public_key); return ret; } @@ -288,6 +373,65 @@ static errno_t ec_pub_key_to_ssh(TALLOC_CTX *mem_ctx, EVP_PKEY *cert_pub_key, #define SSH_RSA_HEADER "ssh-rsa" #define SSH_RSA_HEADER_LEN (sizeof(SSH_RSA_HEADER) - 1) +static int sss_rsa_get_key(EVP_PKEY *cert_pub_key, + BIGNUM **n, BIGNUM **e) +{ + int ret; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + *n = NULL; + ret = EVP_PKEY_get_bn_param(cert_pub_key, OSSL_PKEY_PARAM_RSA_N, discard_const(n)); + if (ret != 1) { + ret = EINVAL; + goto done; + } + + *e = NULL; + ret = EVP_PKEY_get_bn_param(cert_pub_key, OSSL_PKEY_PARAM_RSA_E, discard_const(e)); + if (ret != 1) { + ret = EINVAL; + goto done; + } + +#else + + const BIGNUM *tmp_n; + const BIGNUM *tmp_e: + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + const RSA *rsa_pub_key = NULL; + rsa_pub_key = EVP_PKEY_get0_RSA(cert_pub_key); + if (rsa_pub_key == NULL) { + ret = ENOMEM; + goto done; + } + + RSA_get0_key(rsa_pub_key, tmp_n, tmp_e, NULL); +#else + tmp_n = cert_pub_key->pkey.rsa->n; + tmp_e = cert_pub_key->pkey.rsa->e; +#endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */ + + *n = BN_dup(tmp_n); + if (*n == NULL) { + ret = ENOMEM; + goto done; + } + + *e = BN_dup(tmp_e); + if (*e == NULL) { + BN_clear_free(*n); + ret = ENOMEM; + goto done; + } + +#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */ + + ret = EOK; + +done: + return ret; +} + static errno_t rsa_pub_key_to_ssh(TALLOC_CTX *mem_ctx, EVP_PKEY *cert_pub_key, uint8_t **key_blob, size_t *key_size) { @@ -295,26 +439,18 @@ static errno_t rsa_pub_key_to_ssh(TALLOC_CTX *mem_ctx, EVP_PKEY *cert_pub_key, size_t c; size_t size; uint8_t *buf = NULL; - const BIGNUM *n; - const BIGNUM *e; + BIGNUM *n = NULL; + BIGNUM *e = NULL; int modulus_len; unsigned char modulus[OPENSSL_RSA_MAX_MODULUS_BITS/8]; int exponent_len; unsigned char exponent[OPENSSL_RSA_MAX_PUBEXP_BITS/8]; -#if OPENSSL_VERSION_NUMBER >= 0x10100000L - const RSA *rsa_pub_key = NULL; - rsa_pub_key = EVP_PKEY_get0_RSA(cert_pub_key); - if (rsa_pub_key == NULL) { - ret = ENOMEM; + ret = sss_rsa_get_key(cert_pub_key, &n, &e); + if (ret != EOK) { goto done; } - RSA_get0_key(rsa_pub_key, &n, &e, NULL); -#else - n = cert_pub_key->pkey.rsa->n; - e = cert_pub_key->pkey.rsa->e; -#endif modulus_len = BN_bn2bin(n, modulus); exponent_len = BN_bn2bin(e, exponent); @@ -358,6 +494,9 @@ static errno_t rsa_pub_key_to_ssh(TALLOC_CTX *mem_ctx, EVP_PKEY *cert_pub_key, ret = EOK; done: + BN_clear_free(n); + BN_clear_free(e); + if (ret != EOK) { talloc_free(buf); }