Revert "fetchers: drop support for ancient OpenSSL"

ciworker{8,12} (respectively: FreeBSD, aarch64 Linux) are running
obsolete OS versions. Disappointment ensues.

This reverts commit 6bb70e8810.
This commit is contained in:
John-Mark Bell 2024-02-11 19:05:57 +00:00
parent 6bb70e8810
commit 2a37e5e64c
2 changed files with 328 additions and 31 deletions

View File

@ -134,29 +134,26 @@ static nserror free_ns_cert_info(struct ns_cert_info *cinfo)
#include <openssl/ssl.h>
#include <openssl/x509v3.h>
#if (OPENSSL_VERSION_NUMBER < 0x30000000L)
/* OpenSSL 1.1.1 or LibreSSL */
/* OpenSSL 1.0.x, 1.0.2, 1.1.0 and 1.1.1 API all changed
* LibreSSL declares its OpenSSL version as 2.1 but only supports 1.0.x API
*/
#if (defined(LIBRESSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x1010000fL))
/* 1.0.x */
# if defined(LIBRESSL_VERSION_NUMBER)
/* LibreSSL */
# if (LIBRESSL_VERSION_NUMBER < 0x3050000fL)
/* LibreSSL <3.5.0 */
# if (LIBRESSL_VERSION_NUMBER < 0x2070000fL)
/* LibreSSL <2.7.0 */
#if (defined(LIBRESSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x1000200fL))
/* pre 1.0.2 */
static int ns_X509_get_signature_nid(X509 *cert)
{
return OBJ_obj2nid(cert->cert_info->key->algor->algorithm);
}
#else
#define ns_X509_get_signature_nid X509_get_signature_nid
#endif
static const unsigned char *ns_ASN1_STRING_get0_data(ASN1_STRING *asn1str)
{
return (const unsigned char *)ASN1_STRING_data(asn1str);
}
# else
# define ns_X509_get_signature_nid X509_get_signature_nid
# define ns_ASN1_STRING_get0_data ASN1_STRING_get0_data
# endif
static const BIGNUM *ns_RSA_get0_n(const RSA *d)
{
@ -167,20 +164,298 @@ static const BIGNUM *ns_RSA_get0_e(const RSA *d)
{
return d->e;
}
# else
/* LibreSSL >= 3.5.0 */
# define ns_X509_get_signature_nid X509_get_signature_nid
# define ns_ASN1_STRING_get0_data ASN1_STRING_get0_data
# define ns_RSA_get0_n RSA_get0_n
# define ns_RSA_get0_e RSA_get0_e
# endif
# else
/* OpenSSL 1.1.1 */
# define ns_X509_get_signature_nid X509_get_signature_nid
# define ns_ASN1_STRING_get0_data ASN1_STRING_get0_data
# define ns_RSA_get0_n RSA_get0_n
# define ns_RSA_get0_e RSA_get0_e
# endif
static int ns_EVP_PKEY_get_bn_param(const EVP_PKEY *pkey,
const char *key_name, BIGNUM **bn) {
RSA *rsa;
BIGNUM *result = NULL;
/* Check parameters: only support allocation-form *bn */
if (pkey == NULL || key_name == NULL || bn == NULL || *bn != NULL)
return 0;
/* Only support RSA keys */
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA)
return 0;
rsa = EVP_PKEY_get1_RSA((EVP_PKEY *) pkey);
if (rsa == NULL)
return 0;
if (strcmp(key_name, "n") == 0) {
const BIGNUM *n = ns_RSA_get0_n(rsa);
if (n != NULL)
result = BN_dup(n);
} else if (strcmp(key_name, "e") == 0) {
const BIGNUM *e = ns_RSA_get0_e(rsa);
if (e != NULL)
result = BN_dup(e);
}
RSA_free(rsa);
*bn = result;
return (result != NULL) ? 1 : 0;
}
static int ns_EVP_PKEY_get_utf8_string_param(const EVP_PKEY *pkey,
const char *key_name, char *str, size_t max_len,
size_t *out_len)
{
const EC_GROUP *ecgroup;
const char *group;
EC_KEY *ec;
int ret = 0;
if (pkey == NULL || key_name == NULL)
return 0;
/* Only support EC keys */
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC)
return 0;
/* Only support fetching the group */
if (strcmp(key_name, "group") != 0)
return 0;
ec = EVP_PKEY_get1_EC_KEY((EVP_PKEY *) pkey);
ecgroup = EC_KEY_get0_group(ec);
if (ecgroup == NULL) {
group = "";
} else {
group = OBJ_nid2ln(EC_GROUP_get_curve_name(ecgroup));
}
if (str != NULL && max_len > strlen(group)) {
strcpy(str, group);
str[strlen(group)] = '\0';
ret = 1;
}
if (out_len != NULL)
*out_len = strlen(group);
EC_KEY_free(ec);
return ret;
}
static int ns_EVP_PKEY_get_octet_string_param(const EVP_PKEY *pkey,
const char *key_name, unsigned char *buf, size_t max_len,
size_t *out_len)
{
const EC_GROUP *ecgroup;
const EC_POINT *ecpoint;
size_t len;
BN_CTX *bnctx;
EC_KEY *ec;
int ret = 0;
if (pkey == NULL || key_name == NULL)
return 0;
/* Only support EC keys */
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC)
return 0;
if (strcmp(key_name, "encoded-pub-key") != 0)
return 0;
ec = EVP_PKEY_get1_EC_KEY((EVP_PKEY *) pkey);
if (ec == NULL)
return 0;
ecgroup = EC_KEY_get0_group(ec);
if (ecgroup != NULL) {
ecpoint = EC_KEY_get0_public_key(ec);
if (ecpoint != NULL) {
bnctx = BN_CTX_new();
len = EC_POINT_point2oct(ecgroup,
ecpoint,
POINT_CONVERSION_UNCOMPRESSED,
NULL,
0,
bnctx);
if (len != 0 && len <= max_len) {
if (EC_POINT_point2oct(ecgroup,
ecpoint,
POINT_CONVERSION_UNCOMPRESSED,
buf,
len,
bnctx) == len)
ret = 1;
}
if (out_len != NULL)
*out_len = len;
BN_CTX_free(bnctx);
}
}
EC_KEY_free(ec);
return ret;
}
#elif (OPENSSL_VERSION_NUMBER < 0x1010100fL)
/* 1.1.0 */
#define ns_X509_get_signature_nid X509_get_signature_nid
#define ns_ASN1_STRING_get0_data ASN1_STRING_get0_data
static const BIGNUM *ns_RSA_get0_n(const RSA *r)
{
const BIGNUM *n;
const BIGNUM *e;
const BIGNUM *d;
RSA_get0_key(r, &n, &e, &d);
return n;
}
static const BIGNUM *ns_RSA_get0_e(const RSA *r)
{
const BIGNUM *n;
const BIGNUM *e;
const BIGNUM *d;
RSA_get0_key(r, &n, &e, &d);
return e;
}
static int ns_EVP_PKEY_get_bn_param(const EVP_PKEY *pkey,
const char *key_name, BIGNUM **bn) {
RSA *rsa;
BIGNUM *result = NULL;
/* Check parameters: only support allocation-form *bn */
if (pkey == NULL || key_name == NULL || bn == NULL || *bn != NULL)
return 0;
/* Only support RSA keys */
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA)
return 0;
rsa = EVP_PKEY_get1_RSA((EVP_PKEY *) pkey);
if (rsa == NULL)
return 0;
if (strcmp(key_name, "n") == 0) {
const BIGNUM *n = ns_RSA_get0_n(rsa);
if (n != NULL)
result = BN_dup(n);
} else if (strcmp(key_name, "e") == 0) {
const BIGNUM *e = ns_RSA_get0_e(rsa);
if (e != NULL)
result = BN_dup(e);
}
RSA_free(rsa);
*bn = result;
return (result != NULL) ? 1 : 0;
}
static int ns_EVP_PKEY_get_utf8_string_param(const EVP_PKEY *pkey,
const char *key_name, char *str, size_t max_len,
size_t *out_len)
{
const EC_GROUP *ecgroup;
const char *group;
EC_KEY *ec;
int ret = 0;
if (pkey == NULL || key_name == NULL)
return 0;
/* Only support EC keys */
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC)
return 0;
/* Only support fetching the group */
if (strcmp(key_name, "group") != 0)
return 0;
ec = EVP_PKEY_get1_EC_KEY((EVP_PKEY *) pkey);
ecgroup = EC_KEY_get0_group(ec);
if (ecgroup == NULL) {
group = "";
} else {
group = OBJ_nid2ln(EC_GROUP_get_curve_name(ecgroup));
}
if (str != NULL && max_len > strlen(group)) {
strcpy(str, group);
str[strlen(group)] = '\0';
ret = 1;
}
if (out_len != NULL)
*out_len = strlen(group);
EC_KEY_free(ec);
return ret;
}
static int ns_EVP_PKEY_get_octet_string_param(const EVP_PKEY *pkey,
const char *key_name, unsigned char *buf, size_t max_len,
size_t *out_len)
{
const EC_GROUP *ecgroup;
const EC_POINT *ecpoint;
size_t len;
BN_CTX *bnctx;
EC_KEY *ec;
int ret = 0;
if (pkey == NULL || key_name == NULL)
return 0;
/* Only support EC keys */
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC)
return 0;
if (strcmp(key_name, "encoded-pub-key") != 0)
return 0;
ec = EVP_PKEY_get1_EC_KEY((EVP_PKEY *) pkey);
if (ec == NULL)
return 0;
ecgroup = EC_KEY_get0_group(ec);
if (ecgroup != NULL) {
ecpoint = EC_KEY_get0_public_key(ec);
if (ecpoint != NULL) {
bnctx = BN_CTX_new();
len = EC_POINT_point2oct(ecgroup,
ecpoint,
POINT_CONVERSION_UNCOMPRESSED,
NULL,
0,
bnctx);
if (len != 0 && len <= max_len) {
if (EC_POINT_point2oct(ecgroup,
ecpoint,
POINT_CONVERSION_UNCOMPRESSED,
buf,
len,
bnctx) == len)
ret = 1;
}
if (out_len != NULL)
*out_len = len;
BN_CTX_free(bnctx);
}
}
EC_KEY_free(ec);
return ret;
}
#elif (OPENSSL_VERSION_NUMBER < 0x30000000L)
/* 1.1.1 */
#define ns_X509_get_signature_nid X509_get_signature_nid
#define ns_ASN1_STRING_get0_data ASN1_STRING_get0_data
#define ns_RSA_get0_n RSA_get0_n
#define ns_RSA_get0_e RSA_get0_e
static int ns_EVP_PKEY_get_bn_param(const EVP_PKEY *pkey,
const char *key_name, BIGNUM **bn) {
@ -314,7 +589,7 @@ static int ns_EVP_PKEY_get_octet_string_param(const EVP_PKEY *pkey,
return ret;
}
#else
/* OpenSSL 3.x and later */
/* 3.x and later */
#define ns_X509_get_signature_nid X509_get_signature_nid
#define ns_ASN1_STRING_get0_data ASN1_STRING_get0_data
#define ns_RSA_get0_n RSA_get0_n

View File

@ -106,11 +106,33 @@
#include <openssl/ssl.h>
#include <openssl/x509v3.h>
/* OpenSSL 1.0.x to 1.1.0 certificate reference counting changed
* LibreSSL declares its OpenSSL version as 2.1 but only supports the old way
*/
#if (defined(LIBRESSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x1010000fL))
static int ns_X509_up_ref(X509 *cert)
{
cert->references++;
return 1;
}
static void ns_X509_free(X509 *cert)
{
cert->references--;
if (cert->references == 0) {
X509_free(cert);
}
}
#else
#define ns_X509_up_ref X509_up_ref
#define ns_X509_free X509_free
#endif
#else /* WITH_OPENSSL */
typedef char X509;
static void X509_free(X509 *cert)
static void ns_X509_free(X509 *cert)
{
free(cert);
}
@ -731,7 +753,7 @@ fetch_curl_verify_callback(int verify_ok, X509_STORE_CTX *x509_ctx)
*/
if (!fetch->cert_data[depth].cert) {
fetch->cert_data[depth].cert = X509_STORE_CTX_get_current_cert(x509_ctx);
X509_up_ref(fetch->cert_data[depth].cert);
ns_X509_up_ref(fetch->cert_data[depth].cert);
fetch->cert_data[depth].err = X509_STORE_CTX_get_error(x509_ctx);
}
@ -1456,7 +1478,7 @@ static void fetch_curl_free(void *vf)
/* free certificate data */
for (i = 0; i < MAX_CERT_DEPTH; i++) {
if (f->cert_data[i].cert != NULL) {
X509_free(f->cert_data[i].cert);
ns_X509_free(f->cert_data[i].cert);
}
}