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.

Resolves: #5861
  • Loading branch information
sumit-bose committed Sep 9, 2024
1 parent 604be8d commit 4ec190c
Showing 1 changed file with 140 additions and 23 deletions.
163 changes: 140 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,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,
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)
{
int ret;
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);

Expand Down

0 comments on commit 4ec190c

Please sign in to comment.