]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Improve OpenSSL 4 glue code
authorAlberto Leiva Popper <ydahhrk@gmail.com>
Tue, 14 Jul 2026 19:27:00 +0000 (13:27 -0600)
committerAlberto Leiva Popper <ydahhrk@gmail.com>
Tue, 14 Jul 2026 19:27:00 +0000 (13:27 -0600)
crypto/asn1.h is internal; I'm not supposed to `#include` it.

Also fixes some inoffensive warnings.

src/extension.c
src/libcrypto_util.c
src/object/certificate.c
src/object/name.c
src/str_token.c

index e553763b8545473f6dd67ed08f29bc96a3d9cf9f..4cb98b209260d5bb45416c5d92f6457a4b8bab17 100644 (file)
@@ -1,8 +1,5 @@
 #include "extension.h"
 
-#if OPENSSL_VERSION_MAJOR >= 4
-#include <crypto/asn1.h>
-#endif
 #include <openssl/asn1t.h>
 #include <openssl/obj_mac.h>
 #include <openssl/objects.h>
@@ -123,44 +120,43 @@ static json_t *
 ku2json(void const *ext)
 {
        ASN1_BIT_STRING const *ku = ext;
-       unsigned char data[2];
+       int ku_len;
        json_t *parent;
        json_t *child;
 
-       if (ku->length < 1 || 2 < ku->length)
+       ku_len = ASN1_STRING_length(ku);
+       if (ku_len != 1 || ku_len != 2)
                return NULL;
-       memset(data, 0, sizeof(data));
-       memcpy(data, ku->data, ku->length);
 
        parent = json_obj_new();
        if (parent == NULL)
                return NULL;
 
-       child = json_boolean(data[0] & 0x80u);
+       child = json_boolean(ASN1_BIT_STRING_get_bit(ku, 0));
        if (json_object_add(parent, "digitalSignature", child))
                goto fail;
-       child = json_boolean(data[0] & 0x40u);
+       child = json_boolean(ASN1_BIT_STRING_get_bit(ku, 1));
        if (json_object_add(parent, "contentCommitment", child))
                goto fail;
-       child = json_boolean(data[0] & 0x20u);
+       child = json_boolean(ASN1_BIT_STRING_get_bit(ku, 2));
        if (json_object_add(parent, "keyEncipherment", child))
                goto fail;
-       child = json_boolean(data[0] & 0x10u);
+       child = json_boolean(ASN1_BIT_STRING_get_bit(ku, 3));
        if (json_object_add(parent, "dataEncipherment", child))
                goto fail;
-       child = json_boolean(data[0] & 0x08u);
+       child = json_boolean(ASN1_BIT_STRING_get_bit(ku, 4));
        if (json_object_add(parent, "keyAgreement", child))
                goto fail;
-       child = json_boolean(data[0] & 0x04u);
+       child = json_boolean(ASN1_BIT_STRING_get_bit(ku, 5));
        if (json_object_add(parent, "keyCertSign", child))
                goto fail;
-       child = json_boolean(data[0] & 0x02u);
+       child = json_boolean(ASN1_BIT_STRING_get_bit(ku, 6));
        if (json_object_add(parent, "cRLSign", child))
                goto fail;
-       child = json_boolean(data[0] & 0x01u);
+       child = json_boolean(ASN1_BIT_STRING_get_bit(ku, 7));
        if (json_object_add(parent, "encipherOnly", child))
                goto fail;
-       child = json_boolean(data[1] & 0x80u);
+       child = json_boolean(ASN1_BIT_STRING_get_bit(ku, 8));
        if (json_object_add(parent, "decipherOnly", child))
                goto fail;
 
@@ -453,6 +449,8 @@ static const struct extension_metadata CP = {
 static json_t *
 p2json(ASN1_BIT_STRING const *ap, int af)
 {
+       size_t ap_len;
+       int ap_unused_bits;
        unsigned char bin[16];
        char str[INET6_ADDRSTRLEN];
        unsigned int length;
@@ -462,16 +460,33 @@ p2json(ASN1_BIT_STRING const *ap, int af)
        if (ap == NULL)
                return json_null();
 
+       /* ASN1_BIT_STRING_get_length() thinks length zero is an error... */
+       if (ASN1_STRING_length(ap) == 0) {
+               str[0] = 0;
+               length = 0;
+               goto end;
+       }
+
+#if OPENSSL_VERSION_MAJOR >= 4
+       if (ASN1_BIT_STRING_get_length(ap, &ap_len, &ap_unused_bits) != 1)
+               return json_null();
+#else
+       ap_len = ap->length;
+       ap_unused_bits = (ap->flags & ASN1_STRING_FLAG_BITS_LEFT)
+           ? (ap->flags & 0x07)
+           : 0;
+#endif
+       if (ap_len > 16)
+               return json_null();
+
        memset(bin, 0, sizeof(bin));
-       memcpy(bin, ap->data, ap->length);
+       memcpy(bin, ASN1_STRING_get0_data(ap), ap_len);
        if (inet_ntop(af, bin, str, INET6_ADDRSTRLEN) == NULL)
                return NULL;
 
-       length = 8 * ap->length;
-       if (ap->flags & ASN1_STRING_FLAG_BITS_LEFT)
-               length -= ap->flags & 7;
+       length = 8 * ap_len - ap_unused_bits;
 
-       written = snprintf(full, INET6_ADDRSTRLEN + 4, "%s/%u", str, length);
+end:   written = snprintf(full, INET6_ADDRSTRLEN + 4, "%s/%u", str, length);
        return json_strn_new(full, written);
 }
 
@@ -538,7 +553,8 @@ iaf2json(IPAddressFamily const *iaf)
 {
        json_t *parent;
        json_t *child;
-       ASN1_OCTET_STRING *af;
+       unsigned char const *af_data;
+       int af_len;
        char const *family;
        int afid;
 
@@ -549,14 +565,16 @@ iaf2json(IPAddressFamily const *iaf)
        if (parent == NULL)
                return NULL;
 
-       af = iaf->addressFamily;
-       if (af->length != 2)
+       af_data = ASN1_STRING_get0_data(iaf->addressFamily);
+       af_len = ASN1_STRING_length(iaf->addressFamily);
+
+       if (af_len != 2)
                goto fail;
 
-       if (af->data[0] == 0 && af->data[1] == 1) {
+       if (af_data[0] == 0 && af_data[1] == 1) {
                family = "IPv4";
                afid = AF_INET;
-       } else if (af->data[0] == 0 && af->data[1] == 2) {
+       } else if (af_data[0] == 0 && af_data[1] == 2) {
                family = "IPv6";
                afid = AF_INET6;
        } else {
@@ -938,6 +956,8 @@ validate_public_key_hash(X509 *cert, ASN1_OCTET_STRING *hash)
        X509_PUBKEY const *pubkey;
        const unsigned char *spk;
        int spk_len;
+       unsigned char const *hash_data;
+       int hash_len;
        int ok;
        int error;
 
@@ -981,17 +1001,20 @@ validate_public_key_hash(X509 *cert, ASN1_OCTET_STRING *hash)
        if (!ok)
                return val_crypto_err("X509_PUBKEY_get0_param() returned %d", ok);
 
+       hash_data = ASN1_STRING_get0_data(hash);
+       hash_len = ASN1_STRING_length(hash);
+
        /* Hash the SPK, compare SPK hash with the SKI */
-       if (hash->length < 0 || SIZE_MAX < hash->length) {
+       if (hash_len < 0 || SIZE_MAX < hash_len) {
                return pr_val_err("%s length (%d) is out of bounds. (0-%zu)",
-                   ext_ski()->name, hash->length, SIZE_MAX);
+                   ext_ski()->name, hash_len, SIZE_MAX);
        }
        if (spk_len < 0 || SIZE_MAX < spk_len) {
                return pr_val_err("Subject Public Key length (%d) is out of bounds. (0-%zu)",
                    spk_len, SIZE_MAX);
        }
 
-       error = hash_validate("sha1", hash->data, hash->length, spk, spk_len);
+       error = hash_validate("sha1", hash_data, hash_len, spk, spk_len);
        if (error) {
                pr_val_err("The Subject Public Key's hash does not match the %s.",
                    ext_ski()->name);
index 5ef9c51e6c24713d7e08830e1be7db58c1b43b96..7f95b599aab3ea40a056b7ee435c34eea112d52a 100644 (file)
@@ -1,8 +1,5 @@
 #include "libcrypto_util.h"
 
-#if OPENSSL_VERSION_MAJOR >= 4
-#include <crypto/asn1.h>
-#endif
 #include <openssl/bio.h>
 #include <openssl/bn.h>
 #include <openssl/buffer.h>
@@ -95,6 +92,8 @@ json_t *
 asn1str2json(ASN1_STRING const *str)
 {
        BIO *bio;
+       unsigned char const *str_data;
+       int str_len;
        int i;
 
        if (str == NULL)
@@ -104,8 +103,11 @@ asn1str2json(ASN1_STRING const *str)
        if (bio == NULL)
                return NULL;
 
-       for (i = 0; i < str->length; i++) {
-               if (BIO_printf(bio, "%02x", str->data[i]) <= 0) {
+       str_data = ASN1_STRING_get0_data(str);
+       str_len = ASN1_STRING_length(str);
+
+       for (i = 0; i < str_len; i++) {
+               if (BIO_printf(bio, "%02x", str_data[i]) <= 0) {
                        BIO_free_all(bio);
                        return NULL;
                }
@@ -165,7 +167,8 @@ name2json(X509_NAME const *name)
                if (json_object_add(typeval, "type", child))
                        goto fail;
 
-               child = json_strn_new((char *)data->data, data->length);
+               child = json_strn_new((char *)ASN1_STRING_get0_data(data),
+                   ASN1_STRING_length(data));
                if (json_object_add(typeval, "value", child))
                        goto fail;
        }
@@ -181,13 +184,18 @@ gn2json(GENERAL_NAME *gn)
 {
        ASN1_IA5STRING *str;
        int type;
+       unsigned char const *data;
+       int len;
 
        if (gn == NULL)
                return json_null();
 
        str = GENERAL_NAME_get0_value(gn, &type);
+       data = ASN1_STRING_get0_data(str);
+       len = ASN1_STRING_length(str);
+
        return (type == GEN_URI)
-           ? json_strn_new((char const *)str->data, str->length)
+           ? json_strn_new((char const *)data, len)
            : json_str_new("<Not implemented for now>");
 }
 
index 911bd480ae0b9b6036b3fc4bc9bc0048bcfc2880..53a07ba9750fe630632f933d97383f86719a91e4 100644 (file)
@@ -1,8 +1,5 @@
 #include "object/certificate.h"
 
-#if OPENSSL_VERSION_MAJOR >= 4
-#include <crypto/asn1.h>
-#endif
 #include <openssl/asn1t.h>
 #include <openssl/bio.h>
 #if OPENSSL_VERSION_MAJOR >= 3
@@ -1134,7 +1131,13 @@ abort:
 }
 
 static int
-handle_ip_extension(X509_EXTENSION const *ext, struct resources *resources)
+handle_ip_extension(
+#if OPENSSL_VERSION_MAJOR >= 4
+    X509_EXTENSION const *ext,
+#else
+    X509_EXTENSION *ext,
+#endif
+    struct resources *resources)
 {
        ASN1_OCTET_STRING const *string;
        struct IPAddrBlocks *blocks;
@@ -1143,7 +1146,8 @@ handle_ip_extension(X509_EXTENSION const *ext, struct resources *resources)
        int error;
 
        string = X509_EXTENSION_get_data(ext);
-       error = asn1_decode(string->data, string->length, &asn_DEF_IPAddrBlocks,
+       error = asn1_decode(ASN1_STRING_get0_data(string),
+           ASN1_STRING_length(string), &asn_DEF_IPAddrBlocks,
            (void **) &blocks, true);
        if (error)
                return error;
@@ -1183,16 +1187,22 @@ end:
 }
 
 static int
-handle_asn_extension(X509_EXTENSION const *ext, struct resources *resources,
-    bool allow_inherit)
+handle_asn_extension(
+#if OPENSSL_VERSION_MAJOR >= 4
+    X509_EXTENSION const *ext,
+#else
+    X509_EXTENSION *ext,
+#endif
+    struct resources *resources, bool allow_inherit)
 {
        ASN1_OCTET_STRING const *string;
        struct ASIdentifiers *ids;
        int error;
 
        string = X509_EXTENSION_get_data(ext);
-       error = asn1_decode(string->data, string->length,
-           &asn_DEF_ASIdentifiers, (void **) &ids, true);
+       error = asn1_decode(ASN1_STRING_get0_data(string),
+           ASN1_STRING_length(string), &asn_DEF_ASIdentifiers,
+           (void **) &ids, true);
        if (error)
                return error;
 
@@ -1207,7 +1217,11 @@ __certificate_get_resources(X509 *cert, struct resources *resources,
     int addr_nid, int asn_nid, int bad_addr_nid, int bad_asn_nid,
     char const *policy_rfc, char const *bad_ext_rfc, bool allow_asn_inherit)
 {
+#if OPENSSL_VERSION_MAJOR >= 4
        X509_EXTENSION const *ext;
+#else
+       X509_EXTENSION *ext;
+#endif
        int nid;
        int i;
        int error;
@@ -1296,9 +1310,14 @@ is_rsync(ASN1_IA5STRING *uri)
 {
        static char const *const PREFIX = "rsync://";
        size_t prefix_len = strlen(PREFIX);
+       unsigned char const *uri_data;
+       int uri_len;
 
-       return (uri->length >= prefix_len)
-           ? (strncmp((char *) uri->data, PREFIX, strlen(PREFIX)) == 0)
+       uri_data = ASN1_STRING_get0_data(uri);
+       uri_len = ASN1_STRING_length(uri);
+
+       return (uri_len >= prefix_len)
+           ? (strncmp((char *) uri_data, PREFIX, prefix_len) == 0)
            : false;
 }
 
@@ -1367,6 +1386,8 @@ handle_ski_ee(void *ext, void *arg)
 {
        ASN1_OCTET_STRING *ski = ext;
        struct ski_arguments *args = arg;
+       unsigned char const *ski_data;
+       int ski_len;
        OCTET_STRING_t *sid;
        int error;
 
@@ -1376,11 +1397,11 @@ handle_ski_ee(void *ext, void *arg)
 
        /* rfc6488#section-2.1.6.2 */
        /* rfc6488#section-3.1.c 2/2 */
+       ski_data = ASN1_STRING_get0_data(ski);
+       ski_len = ASN1_STRING_length(ski);
        sid = args->sid;
-       if (ski->length != sid->size
-           || memcmp(ski->data, sid->buf, sid->size) != 0) {
+       if (ski_len != sid->size || memcmp(ski_data, sid->buf, sid->size) != 0)
                return pr_val_err("The EE certificate's subjectKeyIdentifier does not equal the Signed Object's sid.");
-       }
 
        return 0;
 }
@@ -1421,16 +1442,26 @@ handle_ku(ASN1_BIT_STRING *ku, unsigned char byte1)
         * But zeroized rightmost bits can be omitted.
         * This implementation assumes that the ninth bit should always be zero.
         */
-
+       size_t ku_len;
+#if OPENSSL_VERSION_MAJOR >= 4
+       int ku_unused_bits;
+#endif
        unsigned char data[2];
 
-       if (ku->length != 2 && ku->length != 1) {
-               return pr_val_err("Bogus %s length: %d",
-                   ext_ku()->name, ku->length);
+#if OPENSSL_VERSION_MAJOR >= 4
+       if (ASN1_BIT_STRING_get_length(ku, &ku_len, &ku_unused_bits) != 1)
+               return pr_val_err("Cannot read Key Usage string.");
+#else
+       ku_len = ku->length;
+#endif
+
+       if (ku_len != 2 && ku_len != 1) {
+               return pr_val_err("Bogus %s length: %zu",
+                   ext_ku()->name, ku_len);
        }
 
        memset(data, 0, sizeof(data));
-       memcpy(data, ku->data, ku->length);
+       memcpy(data, ASN1_STRING_get0_data(ku), ku_len);
 
        if (data[0] != byte1 || data[1] != 0) {
                return pr_val_err("Illegal key usage flag string: %d%d%d%d%d%d%d%d%d",
index 598781a09d8b1350a92fa085c55414c1a92b06e1..07553ce5850c24275c1abfe758562492b0dbc012 100644 (file)
@@ -1,8 +1,5 @@
 #include "object/name.h"
 
-#if OPENSSL_VERSION_MAJOR >= 4
-#include <crypto/asn1.h>
-#endif
 #include <openssl/asn1.h>
 #include <openssl/obj_mac.h>
 #include <openssl/objects.h>
@@ -27,15 +24,20 @@ static int
 name2string(X509_NAME_ENTRY const *name, char **_result)
 {
        const ASN1_STRING *data;
+       unsigned char const *str;
+       int len;
        char *result;
 
        data = X509_NAME_ENTRY_get_data(name);
        if (data == NULL)
                return val_crypto_err("X509_NAME_ENTRY_get_data() returned NULL");
 
-       result = pmalloc(data->length + 1);
-       memcpy(result, data->data, data->length);
-       result[data->length] = '\0';
+       str = ASN1_STRING_get0_data(data);
+       len = ASN1_STRING_length(data);
+
+       result = pmalloc(len + 1);
+       memcpy(result, str, len);
+       result[len] = '\0';
 
        *_result = result;
        return 0;
index 6963f43b3060a29b4c998dc1ca7263098e5e857d..c44ea537be9e41762b1881262fb7bbb78d37a2d0 100644 (file)
@@ -1,8 +1,5 @@
 #include "str_token.h"
 
-#if OPENSSL_VERSION_MAJOR >= 4
-#include <crypto/asn1.h>
-#endif
 #include <openssl/bio.h>
 #include <stdint.h>
 #include <string.h>
@@ -29,10 +26,8 @@ string_clone(void const *string, size_t size)
 int
 ia5s2string(ASN1_IA5STRING *ia5, char **result)
 {
-       if (ia5->flags & ASN1_STRING_FLAG_BITS_LEFT)
-               return pr_val_err("CRL URI IA5String has unused bits.");
-
-       *result = string_clone(ia5->data, ia5->length);
+       *result = string_clone(ASN1_STRING_get0_data(ia5),
+           ASN1_STRING_length(ia5));
        return 0;
 }