From e99a1fd414153ce578bc57bf5bb1ed0a0968dabc Mon Sep 17 00:00:00 2001 From: tb <> Date: Thu, 21 May 2026 13:14:57 +0000 Subject: rfc3779 test: exercise IPAddressFamily_cmp a bit more This populates an IPAddrBlocks object with not all that sensible data and tests behavior of serialization and deserialization of this thing. Prior to x509_addr.c rev 1.96 this would call memcmp() on NULL. --- src/regress/lib/libcrypto/x509/rfc3779/rfc3779.c | 169 ++++++++++++++++++++++- 1 file changed, 168 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/regress/lib/libcrypto/x509/rfc3779/rfc3779.c b/src/regress/lib/libcrypto/x509/rfc3779/rfc3779.c index 61556f096f..f811749461 100644 --- a/src/regress/lib/libcrypto/x509/rfc3779/rfc3779.c +++ b/src/regress/lib/libcrypto/x509/rfc3779/rfc3779.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rfc3779.c,v 1.12 2026/03/13 06:47:34 tb Exp $ */ +/* $OpenBSD: rfc3779.c,v 1.13 2026/05/21 13:14:57 tb Exp $ */ /* * Copyright (c) 2021 Theo Buehler * @@ -2006,6 +2006,172 @@ run_ASIdentifiers_subset_test(void) return failed; } +/* + * IPAddressFamily_cmp() is well exercised with mostly valid data via canonize + * and is_canonical. Squeeze invalid inheriting address families between valid + * ones, then sort. This would previously call memcmp() on NULL. + */ + +static const uint8_t invalid_block[] = { + 0x30, 0x26, + 0x30, 0x04, 0x04, 0x00, 0x05, 0x00, /* Invalid empty AF. */ + 0x30, 0x06, 0x04, 0x02, 0x00, 0x01, 0x05, 0x00, /* IPv4 */ + 0x30, 0x06, 0x04, 0x02, 0x00, 0x02, 0x05, 0x00, /* IPv6 */ + 0x30, 0x07, 0x04, 0x03, 0x00, 0x02, 0x04, 0x05, 0x00, /* IPv6 NLRI */ + 0x30, 0x05, 0x04, 0x01, 0x01, 0x05, 0x00, /* invalid AF 0x01 */ +}; +static const size_t invalid_block_len = sizeof(invalid_block); + +static int +run_IPAddressFamily_cmp_ub_test(void) +{ + IPAddrBlocks *addrs; + IPAddressFamily *af = NULL; + const unsigned char *p; + unsigned char *out = NULL; + unsigned int nlri_safi = 4; + int out_len = 0; + int failed = 1; + + if ((addrs = IPAddrBlocks_new()) == NULL) { + fprintf(stderr, "%s: IPAddrBlocks_new\n", __func__); + goto err; + } + + /* + * Add IPv6 NLRI, inheriting + */ + if (!X509v3_addr_add_inherit(addrs, IANA_AFI_IPV6, &nlri_safi)) { + fprintf(stderr, "%s: X509v3_addr_add_inherit IPv6\n", __func__); + goto err; + } + + /* + * Add IPv6, inheriting + */ + if (!X509v3_addr_add_inherit(addrs, IANA_AFI_IPV6, NULL)) { + fprintf(stderr, "%s: X509v3_addr_add_inherit IPv6\n", __func__); + goto err; + } + + /* + * Add an inheriting IPAddressFamily with invalid empty addressFamily. + */ + + if ((af = IPAddressFamily_new()) == NULL) { + fprintf(stderr, "%s: IPAddressFamily_new\n", __func__); + goto err; + } + if ((af->ipAddressChoice->u.inherit = ASN1_NULL_new()) == NULL) { + fprintf(stderr, "%s: ASN1_NULL_new()\n", __func__); + goto err; + } + af->ipAddressChoice->type = IPAddressChoice_inherit; + + if (sk_IPAddressFamily_push(addrs, af) <= 0) { + fprintf(stderr, "%s: sk_IPAddressFamily_push\n", __func__); + goto err; + } + af = NULL; + + /* + * Add an inheriting IPAddressFamily with invalid addressFamily 0x01. + */ + + if ((af = IPAddressFamily_new()) == NULL) { + fprintf(stderr, "%s: IPAddressFamily_new\n", __func__); + goto err; + } + if (!ASN1_OCTET_STRING_set(af->addressFamily, "\x01", 1)) { + fprintf(stderr, "%s: ASN1_OCTET_STRING_set\n", __func__); + goto err; + } + if ((af->ipAddressChoice->u.inherit = ASN1_NULL_new()) == NULL) { + fprintf(stderr, "%s: ASN1_NULL_new()\n", __func__); + goto err; + } + af->ipAddressChoice->type = IPAddressChoice_inherit; + + if (sk_IPAddressFamily_push(addrs, af) <= 0) { + fprintf(stderr, "%s: sk_IPAddressFamily_push\n", __func__); + goto err; + } + af = NULL; + + /* + * Add IPv4, inheriting + */ + if (!X509v3_addr_add_inherit(addrs, IANA_AFI_IPV4, NULL)) { + fprintf(stderr, "%s: X509v3_addr_add_inherit IPv4\n", __func__); + goto err; + } + + sk_IPAddressFamily_sort(addrs); + + if (X509v3_addr_is_canonical(addrs)) { + fprintf(stderr, "%s: X509v3_addr_is_canonical\n", __func__); + goto err; + } + + if ((out_len = i2d_IPAddrBlocks(addrs, &out)) <= 0) { + fprintf(stderr, "%s: i2d_IPAddrBlocks failed\n", __func__); + goto err; + } + + if (invalid_block_len != (size_t)out_len) { + fprintf(stderr, "%s: length: want %zu, got %d\n", + __func__, invalid_block_len, out_len); + goto err; + } + + if (memcmp(invalid_block, out, out_len) != 0) { + report_hexdump(__func__, "invalid IPAddrBlock", "memcmp DER failed", + invalid_block, invalid_block_len, out, out_len); + goto err; + } + + /* + * We can also parse this garbage. + */ + + IPAddrBlocks_free(addrs); + addrs = NULL; + + p = invalid_block; + if ((addrs = d2i_IPAddrBlocks(NULL, &p, invalid_block_len)) == NULL) { + fprintf(stderr, "%s: d2i_IPAddrBlocks\n", __func__); + goto err; + } + + freezero(out, out_len); + out = NULL; + + if ((out_len = i2d_IPAddrBlocks(addrs, &out)) <= 0) { + fprintf(stderr, "%s: i2d_IPAddrBlocks (2) failed\n", __func__); + goto err; + } + + if (invalid_block_len != (size_t)out_len) { + fprintf(stderr, "%s: length (2): want %zu, got %d\n", + __func__, invalid_block_len, out_len); + goto err; + } + + if (memcmp(invalid_block, out, out_len) != 0) { + report_hexdump(__func__, "invalid IPAddrBlock (2)", "memcmp DER failed", + invalid_block, invalid_block_len, out, out_len); + goto err; + } + failed = 0; + + err: + IPAddrBlocks_free(addrs); + IPAddressFamily_free(af); + freezero(out, out_len); + + return failed; +} + int main(void) { @@ -2015,6 +2181,7 @@ main(void) failed |= run_IPAddrBlock_tests(); failed |= run_ASIdentifiers_build_test(); failed |= run_ASIdentifiers_subset_test(); + failed |= run_IPAddressFamily_cmp_ub_test(); return failed; } -- cgit v1.2.3-55-g6feb