Commit f08174e914 for openssl.org
commit f08174e91476e1ac9b9bcf79c7d33b11f22b0582
Author: herbenderbler <johnclaus@gmail.com>
Date: Sat Mar 28 21:53:06 2026 -0600
Add public API for IPAddrBlocks (RFC 3779)
Fixes #18528
- Add IPAddrBlocks_new(), IPAddrBlocks_free(), d2i_IPAddrBlocks(),
i2d_IPAddrBlocks(), and IPAddrBlocks_it to the public API.
Reviewed-by: Andrew Dinh <andrewd@openssl.org>
Reviewed-by: Nikola Pajkovsky <nikolap@openssl.org>
Reviewed-by: Neil Horman <nhorman@openssl.org>
MergeDate: Thu Sep 10 21:09:33 2026
(Merged from https://github.com/openssl/openssl/pull/30430)
diff --git a/CHANGES.md b/CHANGES.md
index 24bed46e86..a1a1e6e1e3 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -456,6 +456,14 @@ OpenSSL 4.1
*Adam Tabak*
+ * Added public API for IPAddrBlocks (RFC 3779), mirroring the existing
+ ASIdentifiers API: `IPAddrBlocks_new()`, `IPAddrBlocks_free()`,
+ `d2i_IPAddrBlocks()`, `i2d_IPAddrBlocks()`, and the exported
+ `IPAddrBlocks_it` ASN.1 item for use in custom ASN.1 templates
+ (e.g. RPKI Signed Checklist). Fixes issue #18528.
+
+ *John Claus*
+
* Fixed X.509 verification of certificate chains that use DSA signatures
with SHA-384 or SHA-512 by registering `dsa_with_SHA384` and
`dsa_with_SHA512` in the signature-algorithm cross-reference table.
diff --git a/crypto/x509/v3_addr.c b/crypto/x509/v3_addr.c
index 73ad2345b9..8bf6fed69e 100644
--- a/crypto/x509/v3_addr.c
+++ b/crypto/x509/v3_addr.c
@@ -55,9 +55,11 @@ ASN1_SEQUENCE(IPAddressFamily) = {
ASN1_ITEM_TEMPLATE(IPAddrBlocks) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0,
IPAddrBlocks, IPAddressFamily)
-static_ASN1_ITEM_TEMPLATE_END(IPAddrBlocks)
+ASN1_ITEM_TEMPLATE_END(IPAddrBlocks)
- IMPLEMENT_ASN1_FUNCTIONS(IPAddressRange)
+IMPLEMENT_ASN1_FUNCTIONS_fname(IPAddrBlocks, IPAddrBlocks, IPAddrBlocks)
+
+IMPLEMENT_ASN1_FUNCTIONS(IPAddressRange)
IMPLEMENT_ASN1_FUNCTIONS(IPAddressOrRange)
IMPLEMENT_ASN1_FUNCTIONS(IPAddressChoice)
IMPLEMENT_ASN1_FUNCTIONS(IPAddressFamily)
diff --git a/doc/man3/X509_dup.pod b/doc/man3/X509_dup.pod
index d0b649738b..59fe73a082 100644
--- a/doc/man3/X509_dup.pod
+++ b/doc/man3/X509_dup.pod
@@ -92,6 +92,9 @@ IPAddressOrRange_free,
IPAddressOrRange_new,
IPAddressRange_free,
IPAddressRange_new,
+IPAddrBlocks_free,
+IPAddrBlocks_it,
+IPAddrBlocks_new,
ISSUER_SIGN_TOOL_free,
ISSUER_SIGN_TOOL_it,
ISSUER_SIGN_TOOL_new,
@@ -604,6 +607,9 @@ CMS_EnvelopedData_dup(), OSSL_CRMF_ENCRYPTEDKEY_free(),
OSSL_CRMF_ENCRYPTEDKEY_it() and OSSL_CRMF_ENCRYPTEDKEY_new()
were added in OpenSSL 3.5.
+IPAddrBlocks_free(), IPAddrBlocks_it() and IPAddrBlocks_new()
+were added in OpenSSL 4.1.
+
=head1 COPYRIGHT
Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved.
diff --git a/doc/man3/d2i_X509.pod b/doc/man3/d2i_X509.pod
index aceddddf2f..b37855da16 100644
--- a/doc/man3/d2i_X509.pod
+++ b/doc/man3/d2i_X509.pod
@@ -67,6 +67,7 @@ d2i_IPAddressChoice,
d2i_IPAddressFamily,
d2i_IPAddressOrRange,
d2i_IPAddressRange,
+d2i_IPAddrBlocks,
d2i_ISSUER_SIGN_TOOL,
d2i_ISSUING_DIST_POINT,
d2i_NAMING_AUTHORITY,
@@ -281,6 +282,7 @@ i2d_IPAddressChoice,
i2d_IPAddressFamily,
i2d_IPAddressOrRange,
i2d_IPAddressRange,
+i2d_IPAddrBlocks,
i2d_ISSUER_SIGN_TOOL,
i2d_ISSUING_DIST_POINT,
i2d_NAMING_AUTHORITY,
@@ -765,6 +767,8 @@ i2d_OSSL_TIME_SPEC_TIME(), i2d_OSSL_TIME_SPEC_WEEKS(),
i2d_OSSL_TIME_SPEC_X_DAY_OF()
were added in OpenSSL 3.5.
+d2i_IPAddrBlocks() and i2d_IPAddrBlocks() were added in OpenSSL 4.1.
+
=head1 COPYRIGHT
Copyright 1998-2026 The OpenSSL Project Authors. All Rights Reserved.
diff --git a/include/openssl/x509v3.h.in b/include/openssl/x509v3.h.in
index 21def64b94..34f1c6e69b 100644
--- a/include/openssl/x509v3.h.in
+++ b/include/openssl/x509v3.h.in
@@ -931,6 +931,7 @@ DECLARE_ASN1_FUNCTIONS(IPAddressRange)
DECLARE_ASN1_FUNCTIONS(IPAddressOrRange)
DECLARE_ASN1_FUNCTIONS(IPAddressChoice)
DECLARE_ASN1_FUNCTIONS(IPAddressFamily)
+DECLARE_ASN1_FUNCTIONS(IPAddrBlocks)
/*
* API tag for elements of the ASIdentifier SEQUENCE.
diff --git a/test/v3ext.c b/test/v3ext.c
index 9a47f0ed5b..aa55b36702 100644
--- a/test/v3ext.c
+++ b/test/v3ext.c
@@ -1262,6 +1262,70 @@ end:
return ret;
}
+/*
+ * Regression test for IPAddrBlocks_new/free and d2i/i2d_IPAddrBlocks (issue #18528).
+ * Ensures empty and non-empty IPAddrBlocks round-trip correctly.
+ */
+static int test_ipaddrblocks_api(void)
+{
+ IPAddrBlocks *addr = NULL, *decoded = NULL;
+ ASN1_OCTET_STRING *ip1 = NULL, *ip2 = NULL;
+ unsigned char *der = NULL, *derp;
+ int len;
+ int ret = 0;
+
+ /* Round-trip empty IPAddrBlocks */
+ addr = IPAddrBlocks_new();
+ if (!TEST_ptr(addr))
+ goto end;
+ len = i2d_IPAddrBlocks(addr, &der);
+ if (!TEST_int_ge(len, 0) || !TEST_ptr(der))
+ goto end;
+ derp = der;
+ decoded = d2i_IPAddrBlocks(NULL, (const unsigned char **)&derp, len);
+ if (!TEST_ptr(decoded) || !TEST_int_eq(sk_IPAddressFamily_num(decoded), 0))
+ goto end;
+ IPAddrBlocks_free(addr);
+ IPAddrBlocks_free(decoded);
+ OPENSSL_free(der);
+ addr = decoded = NULL;
+ der = NULL;
+
+ /* Round-trip non-empty IPAddrBlocks and verify structure */
+ addr = IPAddrBlocks_new();
+ if (!TEST_ptr(addr))
+ goto end;
+ if (!TEST_true(X509v3_addr_canonize(addr)))
+ goto end;
+ ip1 = a2i_IPADDRESS(ranges[0].ip1);
+ ip2 = a2i_IPADDRESS(ranges[0].ip2);
+ if (!TEST_ptr(ip1) || !TEST_ptr(ip2))
+ goto end;
+ if (!TEST_true(X509v3_addr_add_range(addr, ranges[0].afi, NULL, ip1->data, ip2->data)))
+ goto end;
+ if (!TEST_true(X509v3_addr_is_canonical(addr)))
+ goto end;
+
+ len = i2d_IPAddrBlocks(addr, &der);
+ if (!TEST_int_ge(len, 0) || !TEST_ptr(der))
+ goto end;
+ derp = der;
+ decoded = d2i_IPAddrBlocks(NULL, (const unsigned char **)&derp, len);
+ if (!TEST_ptr(decoded))
+ goto end;
+ if (!check_addr(decoded, ranges[0].rorp))
+ goto end;
+
+ ret = 1;
+end:
+ IPAddrBlocks_free(addr);
+ IPAddrBlocks_free(decoded);
+ OPENSSL_free(der);
+ ASN1_OCTET_STRING_free(ip1);
+ ASN1_OCTET_STRING_free(ip2);
+ return ret;
+}
+
#endif /* OPENSSL_NO_RFC3779 */
OPT_TEST_DECLARE_USAGE("cert.pem\n")
@@ -1296,6 +1360,7 @@ int setup_tests(void)
ADD_TEST(test_addr_canonize_failure_then_inspect);
ADD_TEST(test_asid_range_merge_canonize);
ADD_TEST(test_asid_canonize_inverted_midsweep);
+ ADD_TEST(test_ipaddrblocks_api);
#endif /* OPENSSL_NO_RFC3779 */
return 1;
}
diff --git a/util/libcrypto.num b/util/libcrypto.num
index a2ff5af75e..fe2d6afb4f 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -5733,3 +5733,8 @@ ASN1_STRING_set1_string ? 4_1_0 EXIST::FUNCTION:
ASN1_STRING_get_length ? 4_1_0 EXIST::FUNCTION:
CMS_add_standard_smimecap_ex ? 4_1_0 EXIST::FUNCTION:CMS
BIO_socket_ready ? 4_1_0 EXIST::FUNCTION:SOCK
+d2i_IPAddrBlocks ? 4_1_0 EXIST::FUNCTION:RFC3779
+i2d_IPAddrBlocks ? 4_1_0 EXIST::FUNCTION:RFC3779
+IPAddrBlocks_free ? 4_1_0 EXIST::FUNCTION:RFC3779
+IPAddrBlocks_new ? 4_1_0 EXIST::FUNCTION:RFC3779
+IPAddrBlocks_it ? 4_1_0 EXIST::FUNCTION:RFC3779