Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft: OpenSSL 3 #260

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
196 changes: 196 additions & 0 deletions dnssec.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
#ifdef USE_DSA
#include <openssl/dsa.h>
#endif
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
#include <openssl/core_names.h>
#endif
#endif

ldns_rr *
Expand Down Expand Up @@ -334,6 +337,7 @@ uint16_t ldns_calc_keytag_raw(const uint8_t* key, size_t keysize)

#ifdef HAVE_SSL
#ifdef USE_DSA
#ifndef OPENSSL_NO_DEPRECATED_3_0
Michael-Panic marked this conversation as resolved.
Show resolved Hide resolved
DSA *
ldns_key_buf2dsa(const ldns_buffer *key)
{
Expand Down Expand Up @@ -409,8 +413,111 @@ ldns_key_buf2dsa_raw(const unsigned char* key, size_t len)
#endif /* OPENSSL_VERSION_NUMBER */
return dsa;
}
#endif /* OPENSSL_NO_DEPRECATED_3_0 */

#if OPENSSL_VERSION_NUMBER >= 0x30000000L

EVP_PKEY *
ldns_dsa2pkey(const ldns_buffer *key)
{
return ldns_dsa2pkey_raw((const unsigned char*)ldns_buffer_begin(key),
ldns_buffer_position(key));
}

EVP_PKEY *
ldns_dsa2pkey_raw(const unsigned char* key, size_t len)
{
uint8_t T;
uint16_t length;
uint16_t offset;
EVP_PKEY_CTX *ctx;
OSSL_PARAM params[5];
EVP_PKEY *pkey = NULL;
unsigned char *Q = NULL;
unsigned char *P = NULL;
unsigned char *G = NULL;
unsigned char *Y = NULL;

if(len == 0)
return NULL;
T = (uint8_t)key[0];
length = (64 + T * 8);
offset = 1;

if (T > 8) {
return NULL;
}
if(len < (size_t)1 + SHA_DIGEST_LENGTH + 3*length)
return NULL;

Q = OPENSSL_zalloc(SHA_DIGEST_LENGTH);
P = OPENSSL_zalloc(length);
G = OPENSSL_zalloc(length);
Y = OPENSSL_zalloc(length);

if (!Q || !P || !G || !Y) {
OPENSSL_clear_free(Q, SHA_DIGEST_LENGTH);
OPENSSL_clear_free(P, length);
OPENSSL_clear_free(G, length);
OPENSSL_clear_free(Y, length);
}

memcpy(Q, key+offset, SHA_DIGEST_LENGTH);
ldns_swap_bytes(Q, SHA_DIGEST_LENGTH);
offset += SHA_DIGEST_LENGTH;

memcpy(P, key+offset, length);
ldns_swap_bytes(P, length);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is using own swap.

offset += length;

memcpy(G, key+offset, length);
ldns_swap_bytes(G, length);
offset += length;

memcpy(Y, key+offset, length);
ldns_swap_bytes(Y, length);

/* Exponent */

params[0] =
OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_FFC_Q, Q, SHA_DIGEST_LENGTH);

params[1] = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_FFC_P, P, length);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may have used OSSL_PARAM_set_BN with combination of BN_bin2bn IMO. Is there a reason it were not used for it and own swap implemented?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. This is an unfortunate requirement for OpenSSL3, but all OSSL_PARAMs must be stored in native byte order instead of network byte order. BIGNUMs created by BN_bin2bn and similar functions store the data in network byte order. This effectively makes OSSL_PARAM_set_BN difficult to use on little-endian systems.

I suppose it would be possible to call BN_lebin2bn to create a backwards BIGNUM on little endian systems, but it's a bit strange because you're calling a function designed to take little endian data on big endian data. It's also weird because you'd have to conditionally call the function based on the endianness of the system.

However, I recall trying this when doing work for libssh2 and finding that it didn't work properly. The only solution that worked for me at the time was swapping the buffer and calling OSSL_PARAM_construct_BN.


params[2] = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_FFC_G, G, length);

params[3] = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_PUB_KEY, Y, length);

params[4] = OSSL_PARAM_construct_end();

ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, NULL);

if(EVP_PKEY_fromdata_init(ctx) <= 0) {
OPENSSL_clear_free(Q, SHA_DIGEST_LENGTH);
OPENSSL_clear_free(P, length);
OPENSSL_clear_free(G, length);
OPENSSL_clear_free(Y, length);
return NULL;
}

if (EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_KEYPAIR, params) <= 0) {
EVP_PKEY_CTX_free(ctx);
OPENSSL_clear_free(Q, SHA_DIGEST_LENGTH);
OPENSSL_clear_free(P, length);
OPENSSL_clear_free(G, length);
OPENSSL_clear_free(Y, length);
return NULL;
}

EVP_PKEY_CTX_free(ctx);

return pkey;
}
#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */

#endif /* USE_DSA */

#ifndef OPENSSL_NO_DEPRECATED_3_0
RSA *
ldns_key_buf2rsa(const ldns_buffer *key)
{
Expand Down Expand Up @@ -485,6 +592,95 @@ ldns_key_buf2rsa_raw(const unsigned char* key, size_t len)

return rsa;
}
#endif /* OPENSSL_NO_DEPRECATED_3_0 */

#if OPENSSL_VERSION_NUMBER >= 0x30000000L
EVP_PKEY *
ldns_rsa2pkey(const ldns_buffer *key)
{
return ldns_rsa2pkey_raw((const unsigned char*)ldns_buffer_begin(key),
ldns_buffer_position(key));
}

EVP_PKEY *
ldns_rsa2pkey_raw(const unsigned char* key, size_t len)
{
uint16_t offset;
uint16_t exp;
uint16_t int16;
EVP_PKEY_CTX *ctx;
OSSL_PARAM params[3];
EVP_PKEY *pkey = NULL;
unsigned char *modulus = NULL;
unsigned char *exponent = NULL;

if (len == 0)
return NULL;
if (key[0] == 0) {
if(len < 3)
return NULL;
/* need some smart comment here XXX*/
/* the exponent is too large so it's places
* further...???? */
memmove(&int16, key+1, 2);
exp = ntohs(int16);
offset = 3;
} else {
exp = key[0];
offset = 1;
}

/* key length at least one */
if(len < (size_t)offset + exp + 1)
return NULL;

/* Exponent */
exponent = OPENSSL_zalloc(exp);
memcpy(exponent, key+offset, exp);
if (!exponent) {
return NULL;
}
ldns_swap_bytes(exponent, exp);
offset += exp;

/* Modulus */
modulus = OPENSSL_zalloc(len - offset);
if(!modulus) {
OPENSSL_clear_free(exponent, exp);
return NULL;
}
/* length of the buffer must match the key length! */
memcpy(modulus, key+offset, len-offset);
ldns_swap_bytes(modulus, len - offset);

params[0] =
OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_RSA_N, modulus, len - offset);

params[1] =
OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_RSA_E, exponent, exp);

params[2] = OSSL_PARAM_construct_end();

ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);

if(EVP_PKEY_fromdata_init(ctx) <= 0) {
OPENSSL_clear_free(modulus, len - offset);
OPENSSL_clear_free(exponent, exp);
return NULL;
}

if (EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_KEYPAIR, params) <= 0) {
EVP_PKEY_CTX_free(ctx);
OPENSSL_clear_free(modulus, len - offset);
OPENSSL_clear_free(exponent, exp);
return NULL;
}

EVP_PKEY_CTX_free(ctx);

return pkey;
}
#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */

int
ldns_digest_evp(const unsigned char* data, unsigned int len, unsigned char* dest,
Expand Down
65 changes: 41 additions & 24 deletions dnssec_sign.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
#ifdef USE_DSA
#include <openssl/dsa.h>
#endif
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
#include <openssl/core_names.h>
#endif
#endif /* HAVE_SSL */

#define LDNS_SIGN_WITH_ZONEMD ( LDNS_SIGN_WITH_ZONEMD_SIMPLE_SHA384 \
Expand Down Expand Up @@ -328,6 +331,7 @@ ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys)
return signatures;
}

#ifndef OPENSSL_NO_DEPRECATED_3_0
ldns_rdf *
ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key)
{
Expand Down Expand Up @@ -400,42 +404,53 @@ ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key)
return NULL;
#endif
}
#endif /* # OPENSSL_NO_DEPRECATED_3_0 */

#ifdef USE_ECDSA
#ifndef S_SPLINT_S
/** returns the number of bytes per signature-component (i.e. bits/8), or 0. */
static int
ldns_pkey_is_ecdsa(EVP_PKEY* pkey)
{
EC_KEY* ec;
const EC_GROUP* g;
#if OPENSSL_VERSION_NUMBER < 0x30000000L
EC_KEY* ec;
const EC_GROUP* g;
#endif

#ifdef HAVE_EVP_PKEY_GET_BASE_ID
if(EVP_PKEY_get_base_id(pkey) != EVP_PKEY_EC)
return 0;
if(EVP_PKEY_get_base_id(pkey) != EVP_PKEY_EC)
return 0;
#elif defined(HAVE_EVP_PKEY_BASE_ID)
if(EVP_PKEY_base_id(pkey) != EVP_PKEY_EC)
return 0;
if(EVP_PKEY_base_id(pkey) != EVP_PKEY_EC)
return 0;
#else
if(EVP_PKEY_type(pkey->type) != EVP_PKEY_EC)
return 0;
if(EVP_PKEY_type(pkey->type) != EVP_PKEY_EC)
return 0;
#endif
ec = EVP_PKEY_get1_EC_KEY(pkey);
g = EC_KEY_get0_group(ec);
if(!g) {
EC_KEY_free(ec);
return 0;
}
if(EC_GROUP_get_curve_name(g) == NID_X9_62_prime256v1) {
EC_KEY_free(ec);
return 32; /* 256/8 */

#if OPENSSL_VERSION_NUMBER >= 0x30000000L
int bits = 0;
EVP_PKEY_get_int_param(pkey, OSSL_PKEY_PARAM_BITS, &bits);
return bits / 8;
#else
ec = EVP_PKEY_get1_EC_KEY(pkey);
g = EC_KEY_get0_group(ec);
if(!g) {
EC_KEY_free(ec);
return 0;
}
if(EC_GROUP_get_curve_name(g) == NID_secp384r1) {
EC_KEY_free(ec);
return 48; /* 384/8 */
}
/* downref the eckey, the original is still inside the pkey */
EC_KEY_free(ec);
return 0;
if(EC_GROUP_get_curve_name(g) == NID_X9_62_prime256v1) {
EC_KEY_free(ec);
return 32; /* 256/8 */
}
if(EC_GROUP_get_curve_name(g) == NID_secp384r1) {
EC_KEY_free(ec);
return 48; /* 384/8 */
}
/* downref the eckey, the original is still inside the pkey */
EC_KEY_free(ec);
return 0;
#endif
}
#endif /* splint */
#endif /* USE_ECDSA */
Expand Down Expand Up @@ -569,6 +584,7 @@ ldns_sign_public_evp(ldns_buffer *to_sign,
return sigdata_rdf;
}

#ifndef OPENSSL_NO_DEPRECATED_3_0
ldns_rdf *
ldns_sign_public_rsasha1(ldns_buffer *to_sign, RSA *key)
{
Expand Down Expand Up @@ -636,6 +652,7 @@ ldns_sign_public_rsamd5(ldns_buffer *to_sign, RSA *key)
ldns_buffer_free(b64sig);
return sigdata_rdf;
}
#endif /* OPENSSL_NO_DEPRECATED_3_0 */
#endif /* HAVE_SSL */

/**
Expand Down
Loading