summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortb <>2022-05-17 08:00:51 +0000
committertb <>2022-05-17 08:00:51 +0000
commitfb501b82535e6677dceed02d6a4a2420f9a8be25 (patch)
tree19fedffbcd0da1a3a418639fe078c3c809dab752 /src
parentcda197b3d8864f040571c54846809867f933099f (diff)
downloadopenbsd-fb501b82535e6677dceed02d6a4a2420f9a8be25.tar.gz
openbsd-fb501b82535e6677dceed02d6a4a2420f9a8be25.tar.bz2
openbsd-fb501b82535e6677dceed02d6a4a2420f9a8be25.zip
Rewrite make_addressRange() using CBS
Factor the trimming of the end and the counting of unused bits into helper functions and reuse an ASN.1 bit string API to set the unused bits and the ASN1_STRING_FLAG_BITS_SET. With a couple of explanatory comments it becomes much clearer what the code is actually doing and why. ok jsing
Diffstat (limited to 'src')
-rw-r--r--src/lib/libcrypto/x509/x509_addr.c141
1 files changed, 104 insertions, 37 deletions
diff --git a/src/lib/libcrypto/x509/x509_addr.c b/src/lib/libcrypto/x509/x509_addr.c
index ba5aaff7e6..e805a14af1 100644
--- a/src/lib/libcrypto/x509/x509_addr.c
+++ b/src/lib/libcrypto/x509/x509_addr.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: x509_addr.c,v 1.81 2022/05/17 07:50:59 tb Exp $ */ 1/* $OpenBSD: x509_addr.c,v 1.82 2022/05/17 08:00:51 tb Exp $ */
2/* 2/*
3 * Contributed to the OpenSSL Project by the American Registry for 3 * Contributed to the OpenSSL Project by the American Registry for
4 * Internet Numbers ("ARIN"). 4 * Internet Numbers ("ARIN").
@@ -894,59 +894,126 @@ make_addressPrefix(IPAddressOrRange **out_aor, uint8_t *addr, uint32_t afi,
894 return 0; 894 return 0;
895} 895}
896 896
897static uint8_t
898count_trailing_zeroes(uint8_t octet)
899{
900 uint8_t count = 0;
901
902 if (octet == 0)
903 return 8;
904
905 while ((octet & (1 << count)) == 0)
906 count++;
907
908 return count;
909}
910
911static int
912trim_end_u8(CBS *cbs, uint8_t trim)
913{
914 uint8_t octet;
915
916 while (CBS_len(cbs) > 0) {
917 if (!CBS_peek_last_u8(cbs, &octet))
918 return 0;
919 if (octet != trim)
920 return 1;
921 if (!CBS_get_last_u8(cbs, &octet))
922 return 0;
923 }
924
925 return 1;
926}
927
897/* 928/*
898 * Construct a range. If it can be expressed as a prefix, 929 * Populate IPAddressOrRange with bit string encoding of a range, see
899 * return a prefix instead. Doing this here simplifies 930 * RFC 3779, 2.1.2.
900 * the rest of the code considerably.
901 */ 931 */
902static int 932static int
903make_addressRange(IPAddressOrRange **result, unsigned char *min, 933make_addressRange(IPAddressOrRange **out_aor, uint8_t *min, uint8_t *max,
904 unsigned char *max, unsigned int afi, int length) 934 uint32_t afi, int length)
905{ 935{
906 IPAddressOrRange *aor; 936 IPAddressOrRange *aor = NULL;
907 int i, prefix_len; 937 IPAddressRange *range;
938 int prefix_len;
939 CBS cbs;
940 size_t max_len, min_len;
941 uint8_t unused_bits_min, unused_bits_max;
942 uint8_t octet;
908 943
909 if (memcmp(min, max, length) > 0) 944 if (memcmp(min, max, length) > 0)
910 return 0; 945 goto err;
946
947 /*
948 * RFC 3779, 2.2.3.6 - a range that can be expressed as a prefix
949 * must be encoded as a prefix.
950 */
911 951
912 if ((prefix_len = range_should_be_prefix(min, max, length)) >= 0) 952 if ((prefix_len = range_should_be_prefix(min, max, length)) >= 0)
913 return make_addressPrefix(result, min, afi, prefix_len); 953 return make_addressPrefix(out_aor, min, afi, prefix_len);
954
955 /*
956 * The bit string representing min is formed by removing all its
957 * trailing zero bits, so remove all trailing zero octets and count
958 * the trailing zero bits of the last octet.
959 */
960
961 CBS_init(&cbs, min, length);
962
963 if (!trim_end_u8(&cbs, 0x00))
964 goto err;
965
966 unused_bits_min = 0;
967 if ((min_len = CBS_len(&cbs)) > 0) {
968 if (!CBS_peek_last_u8(&cbs, &octet))
969 goto err;
970
971 unused_bits_min = count_trailing_zeroes(octet);
972 }
973
974 /*
975 * The bit string representing max is formed by removing all its
976 * trailing one bits, so remove all trailing 0xff octets and count
977 * the trailing ones of the last octet.
978 */
979
980 CBS_init(&cbs, max, length);
981
982 if (!trim_end_u8(&cbs, 0xff))
983 goto err;
984
985 unused_bits_max = 0;
986 if ((max_len = CBS_len(&cbs)) > 0) {
987 if (!CBS_peek_last_u8(&cbs, &octet))
988 goto err;
989
990 unused_bits_max = count_trailing_zeroes(octet + 1);
991 }
992
993 /*
994 * Populate IPAddressOrRange.
995 */
914 996
915 if ((aor = IPAddressOrRange_new()) == NULL) 997 if ((aor = IPAddressOrRange_new()) == NULL)
916 return 0; 998 goto err;
999
917 aor->type = IPAddressOrRange_addressRange; 1000 aor->type = IPAddressOrRange_addressRange;
918 if ((aor->u.addressRange = IPAddressRange_new()) == NULL) 1001
1002 if ((range = aor->u.addressRange = IPAddressRange_new()) == NULL)
919 goto err; 1003 goto err;
920 1004
921 for (i = length; i > 0 && min[i - 1] == 0x00; --i) 1005 if (!ASN1_BIT_STRING_set(range->min, min, min_len))
922 continue; 1006 goto err;
923 if (!ASN1_BIT_STRING_set(aor->u.addressRange->min, min, i)) 1007 if (!asn1_abs_set_unused_bits(range->min, unused_bits_min))
924 goto err; 1008 goto err;
925 aor->u.addressRange->min->flags &= ~7;
926 aor->u.addressRange->min->flags |= ASN1_STRING_FLAG_BITS_LEFT;
927 if (i > 0) {
928 unsigned char b = min[i - 1];
929 int j = 1;
930 while ((b & (0xffU >> j)) != 0)
931 ++j;
932 aor->u.addressRange->min->flags |= 8 - j;
933 }
934 1009
935 for (i = length; i > 0 && max[i - 1] == 0xff; --i) 1010 if (!ASN1_BIT_STRING_set(range->max, max, max_len))
936 continue;
937 if (!ASN1_BIT_STRING_set(aor->u.addressRange->max, max, i))
938 goto err; 1011 goto err;
939 aor->u.addressRange->max->flags &= ~7; 1012 if (!asn1_abs_set_unused_bits(range->max, unused_bits_max))
940 aor->u.addressRange->max->flags |= ASN1_STRING_FLAG_BITS_LEFT; 1013 goto err;
941 if (i > 0) { 1014
942 unsigned char b = max[i - 1]; 1015 *out_aor = aor;
943 int j = 1;
944 while ((b & (0xffU >> j)) != (0xffU >> j))
945 ++j;
946 aor->u.addressRange->max->flags |= 8 - j;
947 }
948 1016
949 *result = aor;
950 return 1; 1017 return 1;
951 1018
952 err: 1019 err: