diff options
author | tb <> | 2022-05-17 08:00:51 +0000 |
---|---|---|
committer | tb <> | 2022-05-17 08:00:51 +0000 |
commit | fb501b82535e6677dceed02d6a4a2420f9a8be25 (patch) | |
tree | 19fedffbcd0da1a3a418639fe078c3c809dab752 /src | |
parent | cda197b3d8864f040571c54846809867f933099f (diff) | |
download | openbsd-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.c | 141 |
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 | ||
897 | static uint8_t | ||
898 | count_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 | |||
911 | static int | ||
912 | trim_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 | */ |
902 | static int | 932 | static int |
903 | make_addressRange(IPAddressOrRange **result, unsigned char *min, | 933 | make_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: |