summaryrefslogtreecommitdiff
path: root/content/fetchers
diff options
context:
space:
mode:
authorJohn-Mark Bell <jmb@netsurf-browser.org>2024-02-11 19:05:57 +0000
committerJohn-Mark Bell <jmb@netsurf-browser.org>2024-02-11 19:06:07 +0000
commit2a37e5e64c153fbc13de557faafd2d1a1493cbdd (patch)
treed56d8074bec8da3c7a2339dbd6f6c3a588d9a13f /content/fetchers
parent6bb70e88108c904d67e9af7c8e5b273f6cd6854f (diff)
downloadnetsurf-2a37e5e64c153fbc13de557faafd2d1a1493cbdd.tar.gz
netsurf-2a37e5e64c153fbc13de557faafd2d1a1493cbdd.tar.bz2
Revert "fetchers: drop support for ancient OpenSSL"
ciworker{8,12} (respectively: FreeBSD, aarch64 Linux) are running obsolete OS versions. Disappointment ensues. This reverts commit 6bb70e88108c904d67e9af7c8e5b273f6cd6854f.
Diffstat (limited to 'content/fetchers')
-rw-r--r--content/fetchers/about/certificate.c331
-rw-r--r--content/fetchers/curl.c28
2 files changed, 328 insertions, 31 deletions
diff --git a/content/fetchers/about/certificate.c b/content/fetchers/about/certificate.c
index 6f634d22a..554f06eb8 100644
--- a/content/fetchers/about/certificate.c
+++ b/content/fetchers/about/certificate.c
@@ -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 */
-
-# if defined(LIBRESSL_VERSION_NUMBER)
- /* LibreSSL */
-# if (LIBRESSL_VERSION_NUMBER < 0x3050000fL)
- /* LibreSSL <3.5.0 */
+/* 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 (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
diff --git a/content/fetchers/curl.c b/content/fetchers/curl.c
index b1907448e..6878d9e6a 100644
--- a/content/fetchers/curl.c
+++ b/content/fetchers/curl.c
@@ -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);
}
}