From 29660b6745f0be878450665971dbee74706f1f58 Mon Sep 17 00:00:00 2001 From: David Uhden Collado Date: Mon, 13 Oct 2025 22:56:56 +0200 Subject: [PATCH] Improve LibreSSL compatibility --- libi2pd/Crypto.cpp | 58 +++++++++++++++++++++++++++++++++++++++++++ libi2pd/Crypto.h | 2 ++ libi2pd/Family.cpp | 18 ++------------ libi2pd/Signature.cpp | 49 ++++++++++++++++++++++++++---------- 4 files changed, 98 insertions(+), 29 deletions(-) diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index 27c673e7..653f03f3 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -15,9 +15,11 @@ #include #include #include +#include #include "TunnelBase.h" #include #include +#include #if I2PD_OPENSSL_GE_3 // since 3.0.0 #include #include @@ -137,6 +139,62 @@ namespace crypto return true; } + EVP_PKEY * GenerateECKey (int curve) + { + #if I2PD_OPENSSL_GE_3 + return EVP_EC_gen (OBJ_nid2ln (curve)); + #else + EC_KEY * ec = EC_KEY_new_by_curve_name (curve); + if (!ec) + { + LogPrint (eLogError, "Crypto: Failed to allocate EC key for curve ", curve); + return nullptr; + } + if (!EC_KEY_generate_key (ec)) + { + LogPrint (eLogError, "Crypto: Failed to generate EC key for curve ", curve); + EC_KEY_free (ec); + return nullptr; + } + EVP_PKEY * pkey = EVP_PKEY_new (); + if (!pkey) + { + LogPrint (eLogError, "Crypto: Failed to allocate EVP_PKEY for EC curve ", curve); + EC_KEY_free (ec); + return nullptr; + } + if (!EVP_PKEY_assign_EC_KEY (pkey, ec)) + { + LogPrint (eLogError, "Crypto: EVP_PKEY_assign_EC_KEY failed for curve ", curve); + EVP_PKEY_free (pkey); + EC_KEY_free (ec); + return nullptr; + } + return pkey; + #endif + } + + int GetEVPKeyCurveNID (const EVP_PKEY * pkey) + { + if (!pkey) return -1; + #if I2PD_OPENSSL_GE_3 + char groupName[64]; + if (EVP_PKEY_get_group_name (const_cast(pkey), groupName, sizeof (groupName), NULL) == 1) + return OBJ_txt2nid (groupName); + return -1; + #else + if (EVP_PKEY_base_id (pkey) != EVP_PKEY_EC) + return 0; + EC_KEY * ec = EVP_PKEY_get1_EC_KEY (const_cast(pkey)); + if (!ec) + return -1; + const EC_GROUP * group = EC_KEY_get0_group (ec); + int nid = group ? EC_GROUP_get_curve_name (group) : -1; + EC_KEY_free (ec); + return nid; + #endif + } + // RSA #define rsae GetCryptoConstants ().rsae const BIGNUM * GetRSAE () diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index b6646868..94cf748e 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -48,6 +48,8 @@ namespace i2p namespace crypto { bool bn2buf (const BIGNUM * bn, uint8_t * buf, size_t len); + EVP_PKEY * GenerateECKey (int curve); + int GetEVPKeyCurveNID (const EVP_PKEY * pkey); // DSA #if I2PD_OPENSSL_GE_3 // since 3.0.0 diff --git a/libi2pd/Family.cpp b/libi2pd/Family.cpp index c07ab238..62bb506b 100644 --- a/libi2pd/Family.cpp +++ b/libi2pd/Family.cpp @@ -51,14 +51,7 @@ namespace data auto pkey = X509_get_pubkey (cert); if (pkey) { - int curve = 0; -#if I2PD_OPENSSL_GE_3 // since 3.0.0 - char groupName[20]; - if (EVP_PKEY_get_group_name(pkey, groupName, sizeof(groupName), NULL) == 1) - curve = OBJ_txt2nid (groupName); - else - curve = -1; -#endif + int curve = i2p::crypto::GetEVPKeyCurveNID (pkey); if (!curve || curve == NID_X9_62_prime256v1) { if (!m_SigningKeys.emplace (cn, std::make_pair(pkey, (int)m_SigningKeys.size () + 1)).second) @@ -156,14 +149,7 @@ namespace data { SSL * ssl = SSL_new (ctx); EVP_PKEY * pkey = SSL_get_privatekey (ssl); - int curve = 0; -#if I2PD_OPENSSL_GE_3 // since 3.0.0 - char groupName[20]; - if (EVP_PKEY_get_group_name(pkey, groupName, sizeof(groupName), NULL) == 1) - curve = OBJ_txt2nid (groupName); - else - curve = -1; -#endif + int curve = i2p::crypto::GetEVPKeyCurveNID (pkey); if (!curve || curve == NID_X9_62_prime256v1) { uint8_t buf[100], sign[72], signature[64]; diff --git a/libi2pd/Signature.cpp b/libi2pd/Signature.cpp index 96565a30..c2dec897 100644 --- a/libi2pd/Signature.cpp +++ b/libi2pd/Signature.cpp @@ -7,6 +7,7 @@ */ #include +#include #include "Crypto.h" #include #if I2PD_OPENSSL_GE_3 // since 3.0.0 @@ -286,19 +287,41 @@ namespace crypto void CreateECDSARandomKeys (int curve, size_t keyLen, uint8_t * signingPrivateKey, uint8_t * signingPublicKey) { - EVP_PKEY * pkey = EVP_EC_gen (OBJ_nid2ln(curve)); - // private - BIGNUM * priv = BN_new (); - EVP_PKEY_get_bn_param (pkey, OSSL_PKEY_PARAM_PRIV_KEY, &priv); - bn2buf (priv, signingPrivateKey, keyLen/2); - BN_free (priv); - // public - BIGNUM * x = BN_new (), * y = BN_new (); - EVP_PKEY_get_bn_param (pkey, OSSL_PKEY_PARAM_EC_PUB_X, &x); - EVP_PKEY_get_bn_param (pkey, OSSL_PKEY_PARAM_EC_PUB_Y, &y); - bn2buf (x, signingPublicKey, keyLen/2); - bn2buf (y, signingPublicKey + keyLen/2, keyLen/2); - BN_free (x); BN_free (y); + auto pkey = GenerateECKey (curve); + if (!pkey) + return; + EC_KEY * ec = EVP_PKEY_get1_EC_KEY (pkey); + if (!ec) + { + LogPrint (eLogError, "ECDSA: Failed to extract EC key for curve ", curve); + EVP_PKEY_free (pkey); + return; + } + const BIGNUM * priv = EC_KEY_get0_private_key (ec); + if (priv) + bn2buf (priv, signingPrivateKey, keyLen/2); + else + memset (signingPrivateKey, 0, keyLen/2); + const EC_GROUP * group = EC_KEY_get0_group (ec); + const EC_POINT * pub = EC_KEY_get0_public_key (ec); + if (group && pub) + { + BIGNUM * x = BN_new (), * y = BN_new (); + BN_CTX * ctx = BN_CTX_new (); + if (x && y && ctx && EC_POINT_get_affine_coordinates_GFp (group, pub, x, y, ctx)) + { + bn2buf (x, signingPublicKey, keyLen/2); + bn2buf (y, signingPublicKey + keyLen/2, keyLen/2); + } + else + LogPrint (eLogError, "ECDSA: Failed to extract public coordinates for curve ", curve); + if (ctx) BN_CTX_free (ctx); + if (x) BN_free (x); + if (y) BN_free (y); + } + else + LogPrint (eLogError, "ECDSA: Missing group or public key for curve ", curve); + EC_KEY_free (ec); EVP_PKEY_free (pkey); }