diff --git a/src/util/cert/libcrypto/cert.c b/src/util/cert/libcrypto/cert.c index 61908c7f048..24de7a79833 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,46 @@ 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, + const BIGNUM **n, const 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; + } + + /* n and e must be freed later */ +#elif 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, n, e, NULL); +#else + *n = cert_pub_key->pkey.rsa->n; + *e = cert_pub_key->pkey.rsa->e; +#endif + + 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 +420,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; + const BIGNUM *n = NULL; + const 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);