summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authortb <>2023-12-25 22:02:59 +0000
committertb <>2023-12-25 22:02:59 +0000
commit73b7427c3c99104d3110af3bddc5fa8049963cd7 (patch)
tree90d476cacff75c553be0c9a1bd40589eff75659d /src/lib
parent6fbc05f87ce487143e055a99f6450628fef7d792 (diff)
downloadopenbsd-73b7427c3c99104d3110af3bddc5fa8049963cd7.tar.gz
openbsd-73b7427c3c99104d3110af3bddc5fa8049963cd7.tar.bz2
openbsd-73b7427c3c99104d3110af3bddc5fa8049963cd7.zip
Avoid out-of-bounds accesses in ASN1_BIT_STRING_{get,set}()
If a negative n is passed, these functions would underrun the bitstring's data array. So add checks for that and drop spades of unnecessary parens. These functions are quite broken anyway. The setter attempts to zap the unnecessary trailing zero octets, but fails to do so if the bit being cleared isn't already set. Worse is the getter where you can't tell an error (like attempting an out-of-bounds read) from the bit being unset. ok joshua
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libcrypto/asn1/a_bitstr.c40
1 files changed, 26 insertions, 14 deletions
diff --git a/src/lib/libcrypto/asn1/a_bitstr.c b/src/lib/libcrypto/asn1/a_bitstr.c
index 7ea3e12b91..851a3a3d51 100644
--- a/src/lib/libcrypto/asn1/a_bitstr.c
+++ b/src/lib/libcrypto/asn1/a_bitstr.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: a_bitstr.c,v 1.41 2023/07/28 10:33:13 tb Exp $ */ 1/* $OpenBSD: a_bitstr.c,v 1.42 2023/12/25 22:02:59 tb Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -120,20 +120,24 @@ ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value)
120 int w, v, iv; 120 int w, v, iv;
121 unsigned char *c; 121 unsigned char *c;
122 122
123 w = n/8; 123 if (a == NULL)
124 return 0;
125 if (n < 0)
126 return 0;
127
128 w = n / 8;
124 v = 1 << (7 - (n & 0x07)); 129 v = 1 << (7 - (n & 0x07));
125 iv = ~v; 130 iv = ~v;
126 if (!value)
127 v = 0;
128 131
129 if (a == NULL) 132 if (value == 0)
130 return 0; 133 v = 0;
131 134
132 asn1_abs_clear_unused_bits(a); 135 asn1_abs_clear_unused_bits(a);
133 136
134 if ((a->length < (w + 1)) || (a->data == NULL)) { 137 if (a->length < w + 1 || a->data == NULL) {
135 if (!value) 138 /* Don't expand if there's no bit to set. */
136 return(1); /* Don't need to set */ 139 if (value == 0)
140 return 1;
137 if ((c = recallocarray(a->data, a->length, w + 1, 1)) == NULL) { 141 if ((c = recallocarray(a->data, a->length, w + 1, 1)) == NULL) {
138 ASN1error(ERR_R_MALLOC_FAILURE); 142 ASN1error(ERR_R_MALLOC_FAILURE);
139 return 0; 143 return 0;
@@ -141,11 +145,12 @@ ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value)
141 a->data = c; 145 a->data = c;
142 a->length = w + 1; 146 a->length = w + 1;
143 } 147 }
148
144 a->data[w] = ((a->data[w]) & iv) | v; 149 a->data[w] = ((a->data[w]) & iv) | v;
145 while ((a->length > 0) && (a->data[a->length - 1] == 0)) 150 while (a->length > 0 && a->data[a->length - 1] == 0)
146 a->length--; 151 a->length--;
147 152
148 return (1); 153 return 1;
149} 154}
150LCRYPTO_ALIAS(ASN1_BIT_STRING_set_bit); 155LCRYPTO_ALIAS(ASN1_BIT_STRING_set_bit);
151 156
@@ -154,11 +159,18 @@ ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *a, int n)
154{ 159{
155 int w, v; 160 int w, v;
156 161
162 if (a == NULL)
163 return 0;
164 if (n < 0)
165 return 0;
166
157 w = n / 8; 167 w = n / 8;
158 v = 1 << (7 - (n & 0x07)); 168 v = 1 << (7 - (n & 0x07));
159 if ((a == NULL) || (a->length < (w + 1)) || (a->data == NULL)) 169
160 return (0); 170 if (a->length < w + 1 || a->data == NULL)
161 return ((a->data[w] & v) != 0); 171 return 0;
172
173 return (a->data[w] & v) != 0;
162} 174}
163LCRYPTO_ALIAS(ASN1_BIT_STRING_get_bit); 175LCRYPTO_ALIAS(ASN1_BIT_STRING_get_bit);
164 176