Skip to content

Commit

Permalink
cert util: replace deprecated OpenSSL calls
Browse files Browse the repository at this point in the history
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: #5861
  • Loading branch information
sumit-bose committed Sep 11, 2024
1 parent 0be58a2 commit 56e08e4
Showing 1 changed file with 162 additions and 23 deletions.
185 changes: 162 additions & 23 deletions src/util/cert/libcrypto/cert.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <openssl/x509.h>
#include <openssl/bio.h>
#include <openssl/pem.h>
#include <openssl/core_names.h>

#include "util/util.h"
#include "util/sss_endian.h"
Expand Down Expand Up @@ -176,31 +177,116 @@ 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)
{
int ret;
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;
int identifier_len;
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;
Expand All @@ -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");
Expand Down Expand Up @@ -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;
}
Expand All @@ -288,33 +373,84 @@ 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, _n);
if (ret != 1) {
ret = EINVAL;
goto done;
}

*_e = NULL;
ret = EVP_PKEY_get_bn_param(cert_pub_key, OSSL_PKEY_PARAM_RSA_E, _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)
{
int ret;
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);

Expand Down Expand Up @@ -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);
}
Expand Down

0 comments on commit 56e08e4

Please sign in to comment.