/src/libressl/crypto/asn1/a_bitstr.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* $OpenBSD: a_bitstr.c,v 1.36 2022/05/17 09:17:20 tb Exp $ */ |
2 | | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | | * All rights reserved. |
4 | | * |
5 | | * This package is an SSL implementation written |
6 | | * by Eric Young (eay@cryptsoft.com). |
7 | | * The implementation was written so as to conform with Netscapes SSL. |
8 | | * |
9 | | * This library is free for commercial and non-commercial use as long as |
10 | | * the following conditions are aheared to. The following conditions |
11 | | * apply to all code found in this distribution, be it the RC4, RSA, |
12 | | * lhash, DES, etc., code; not just the SSL code. The SSL documentation |
13 | | * included with this distribution is covered by the same copyright terms |
14 | | * except that the holder is Tim Hudson (tjh@cryptsoft.com). |
15 | | * |
16 | | * Copyright remains Eric Young's, and as such any Copyright notices in |
17 | | * the code are not to be removed. |
18 | | * If this package is used in a product, Eric Young should be given attribution |
19 | | * as the author of the parts of the library used. |
20 | | * This can be in the form of a textual message at program startup or |
21 | | * in documentation (online or textual) provided with the package. |
22 | | * |
23 | | * Redistribution and use in source and binary forms, with or without |
24 | | * modification, are permitted provided that the following conditions |
25 | | * are met: |
26 | | * 1. Redistributions of source code must retain the copyright |
27 | | * notice, this list of conditions and the following disclaimer. |
28 | | * 2. Redistributions in binary form must reproduce the above copyright |
29 | | * notice, this list of conditions and the following disclaimer in the |
30 | | * documentation and/or other materials provided with the distribution. |
31 | | * 3. All advertising materials mentioning features or use of this software |
32 | | * must display the following acknowledgement: |
33 | | * "This product includes cryptographic software written by |
34 | | * Eric Young (eay@cryptsoft.com)" |
35 | | * The word 'cryptographic' can be left out if the rouines from the library |
36 | | * being used are not cryptographic related :-). |
37 | | * 4. If you include any Windows specific code (or a derivative thereof) from |
38 | | * the apps directory (application code) you must include an acknowledgement: |
39 | | * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
40 | | * |
41 | | * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
42 | | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
43 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
44 | | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
45 | | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
46 | | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
47 | | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
48 | | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
49 | | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
50 | | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
51 | | * SUCH DAMAGE. |
52 | | * |
53 | | * The licence and distribution terms for any publically available version or |
54 | | * derivative of this code cannot be changed. i.e. this code cannot simply be |
55 | | * copied and put under another distribution licence |
56 | | * [including the GNU Public Licence.] |
57 | | */ |
58 | | |
59 | | #include <limits.h> |
60 | | #include <stdio.h> |
61 | | #include <string.h> |
62 | | |
63 | | #include <openssl/asn1.h> |
64 | | #include <openssl/asn1t.h> |
65 | | #include <openssl/conf.h> |
66 | | #include <openssl/err.h> |
67 | | #include <openssl/x509v3.h> |
68 | | |
69 | | #include "bytestring.h" |
70 | | |
71 | | const ASN1_ITEM ASN1_BIT_STRING_it = { |
72 | | .itype = ASN1_ITYPE_PRIMITIVE, |
73 | | .utype = V_ASN1_BIT_STRING, |
74 | | .sname = "ASN1_BIT_STRING", |
75 | | }; |
76 | | |
77 | | ASN1_BIT_STRING * |
78 | | ASN1_BIT_STRING_new(void) |
79 | 42.5k | { |
80 | 42.5k | return (ASN1_BIT_STRING *)ASN1_item_new(&ASN1_BIT_STRING_it); |
81 | 42.5k | } |
82 | | |
83 | | void |
84 | | ASN1_BIT_STRING_free(ASN1_BIT_STRING *a) |
85 | 79.0k | { |
86 | 79.0k | ASN1_item_free((ASN1_VALUE *)a, &ASN1_BIT_STRING_it); |
87 | 79.0k | } |
88 | | |
89 | | static void |
90 | | asn1_abs_clear_unused_bits(ASN1_BIT_STRING *abs) |
91 | 42.5k | { |
92 | 42.5k | abs->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); |
93 | 42.5k | } |
94 | | |
95 | | int |
96 | | asn1_abs_set_unused_bits(ASN1_BIT_STRING *abs, uint8_t unused_bits) |
97 | 42.5k | { |
98 | 42.5k | if (unused_bits > 7) |
99 | 6 | return 0; |
100 | | |
101 | 42.5k | asn1_abs_clear_unused_bits(abs); |
102 | | |
103 | 42.5k | abs->flags |= ASN1_STRING_FLAG_BITS_LEFT | unused_bits; |
104 | | |
105 | 42.5k | return 1; |
106 | 42.5k | } |
107 | | |
108 | | int |
109 | | ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len) |
110 | 0 | { |
111 | 0 | return ASN1_STRING_set(x, d, len); |
112 | 0 | } |
113 | | |
114 | | int |
115 | | ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value) |
116 | 0 | { |
117 | 0 | int w, v, iv; |
118 | 0 | unsigned char *c; |
119 | |
|
120 | 0 | w = n/8; |
121 | 0 | v = 1 << (7 - (n & 0x07)); |
122 | 0 | iv = ~v; |
123 | 0 | if (!value) |
124 | 0 | v = 0; |
125 | |
|
126 | 0 | if (a == NULL) |
127 | 0 | return 0; |
128 | | |
129 | 0 | asn1_abs_clear_unused_bits(a); |
130 | |
|
131 | 0 | if ((a->length < (w + 1)) || (a->data == NULL)) { |
132 | 0 | if (!value) |
133 | 0 | return(1); /* Don't need to set */ |
134 | 0 | if ((c = recallocarray(a->data, a->length, w + 1, 1)) == NULL) { |
135 | 0 | ASN1error(ERR_R_MALLOC_FAILURE); |
136 | 0 | return 0; |
137 | 0 | } |
138 | 0 | a->data = c; |
139 | 0 | a->length = w + 1; |
140 | 0 | } |
141 | 0 | a->data[w] = ((a->data[w]) & iv) | v; |
142 | 0 | while ((a->length > 0) && (a->data[a->length - 1] == 0)) |
143 | 0 | a->length--; |
144 | |
|
145 | 0 | return (1); |
146 | 0 | } |
147 | | |
148 | | int |
149 | | ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *a, int n) |
150 | 0 | { |
151 | 0 | int w, v; |
152 | |
|
153 | 0 | w = n / 8; |
154 | 0 | v = 1 << (7 - (n & 0x07)); |
155 | 0 | if ((a == NULL) || (a->length < (w + 1)) || (a->data == NULL)) |
156 | 0 | return (0); |
157 | 0 | return ((a->data[w] & v) != 0); |
158 | 0 | } |
159 | | |
160 | | /* |
161 | | * Checks if the given bit string contains only bits specified by |
162 | | * the flags vector. Returns 0 if there is at least one bit set in 'a' |
163 | | * which is not specified in 'flags', 1 otherwise. |
164 | | * 'len' is the length of 'flags'. |
165 | | */ |
166 | | int |
167 | | ASN1_BIT_STRING_check(const ASN1_BIT_STRING *a, const unsigned char *flags, |
168 | | int flags_len) |
169 | 0 | { |
170 | 0 | int i, ok; |
171 | | |
172 | | /* Check if there is one bit set at all. */ |
173 | 0 | if (!a || !a->data) |
174 | 0 | return 1; |
175 | | |
176 | | /* Check each byte of the internal representation of the bit string. */ |
177 | 0 | ok = 1; |
178 | 0 | for (i = 0; i < a->length && ok; ++i) { |
179 | 0 | unsigned char mask = i < flags_len ? ~flags[i] : 0xff; |
180 | | /* We are done if there is an unneeded bit set. */ |
181 | 0 | ok = (a->data[i] & mask) == 0; |
182 | 0 | } |
183 | 0 | return ok; |
184 | 0 | } |
185 | | |
186 | | int |
187 | | ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs, |
188 | | BIT_STRING_BITNAME *tbl, int indent) |
189 | 0 | { |
190 | 0 | BIT_STRING_BITNAME *bnam; |
191 | 0 | char first = 1; |
192 | |
|
193 | 0 | BIO_printf(out, "%*s", indent, ""); |
194 | 0 | for (bnam = tbl; bnam->lname; bnam++) { |
195 | 0 | if (ASN1_BIT_STRING_get_bit(bs, bnam->bitnum)) { |
196 | 0 | if (!first) |
197 | 0 | BIO_puts(out, ", "); |
198 | 0 | BIO_puts(out, bnam->lname); |
199 | 0 | first = 0; |
200 | 0 | } |
201 | 0 | } |
202 | 0 | BIO_puts(out, "\n"); |
203 | 0 | return 1; |
204 | 0 | } |
205 | | |
206 | | int |
207 | | ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, const char *name, int value, |
208 | | BIT_STRING_BITNAME *tbl) |
209 | 0 | { |
210 | 0 | int bitnum; |
211 | |
|
212 | 0 | bitnum = ASN1_BIT_STRING_num_asc(name, tbl); |
213 | 0 | if (bitnum < 0) |
214 | 0 | return 0; |
215 | 0 | if (bs) { |
216 | 0 | if (!ASN1_BIT_STRING_set_bit(bs, bitnum, value)) |
217 | 0 | return 0; |
218 | 0 | } |
219 | 0 | return 1; |
220 | 0 | } |
221 | | |
222 | | int |
223 | | ASN1_BIT_STRING_num_asc(const char *name, BIT_STRING_BITNAME *tbl) |
224 | 0 | { |
225 | 0 | BIT_STRING_BITNAME *bnam; |
226 | |
|
227 | 0 | for (bnam = tbl; bnam->lname; bnam++) { |
228 | 0 | if (!strcmp(bnam->sname, name) || |
229 | 0 | !strcmp(bnam->lname, name)) |
230 | 0 | return bnam->bitnum; |
231 | 0 | } |
232 | 0 | return -1; |
233 | 0 | } |
234 | | |
235 | | int |
236 | | i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp) |
237 | 65.6k | { |
238 | 65.6k | int ret, j, bits, len; |
239 | 65.6k | unsigned char *p, *d; |
240 | | |
241 | 65.6k | if (a == NULL) |
242 | 0 | return (0); |
243 | | |
244 | 65.6k | len = a->length; |
245 | | |
246 | 65.6k | if (len > 0) { |
247 | 65.5k | if (a->flags & ASN1_STRING_FLAG_BITS_LEFT) { |
248 | 65.5k | bits = (int)a->flags & 0x07; |
249 | 65.5k | } else { |
250 | 0 | for (; len > 0; len--) { |
251 | 0 | if (a->data[len - 1]) |
252 | 0 | break; |
253 | 0 | } |
254 | 0 | j = a->data[len - 1]; |
255 | 0 | if (j & 0x01) |
256 | 0 | bits = 0; |
257 | 0 | else if (j & 0x02) |
258 | 0 | bits = 1; |
259 | 0 | else if (j & 0x04) |
260 | 0 | bits = 2; |
261 | 0 | else if (j & 0x08) |
262 | 0 | bits = 3; |
263 | 0 | else if (j & 0x10) |
264 | 0 | bits = 4; |
265 | 0 | else if (j & 0x20) |
266 | 0 | bits = 5; |
267 | 0 | else if (j & 0x40) |
268 | 0 | bits = 6; |
269 | 0 | else if (j & 0x80) |
270 | 0 | bits = 7; |
271 | 0 | else |
272 | 0 | bits = 0; /* should not happen */ |
273 | 0 | } |
274 | 65.5k | } else |
275 | 15 | bits = 0; |
276 | | |
277 | 65.6k | ret = 1 + len; |
278 | 65.6k | if (pp == NULL) |
279 | 49.2k | return (ret); |
280 | | |
281 | 16.3k | p= *pp; |
282 | | |
283 | 16.3k | *(p++) = (unsigned char)bits; |
284 | 16.3k | d = a->data; |
285 | 16.3k | if (len > 0) { |
286 | 16.3k | memcpy(p, d, len); |
287 | 16.3k | p += len; |
288 | 16.3k | p[-1] &= 0xff << bits; |
289 | 16.3k | } |
290 | 16.3k | *pp = p; |
291 | 16.3k | return (ret); |
292 | 65.6k | } |
293 | | |
294 | | int |
295 | | c2i_ASN1_BIT_STRING_cbs(ASN1_BIT_STRING **out_abs, CBS *cbs) |
296 | 42.5k | { |
297 | 42.5k | ASN1_BIT_STRING *abs = NULL; |
298 | 42.5k | uint8_t *data = NULL; |
299 | 42.5k | size_t data_len = 0; |
300 | 42.5k | uint8_t unused_bits; |
301 | 42.5k | int ret = 0; |
302 | | |
303 | 42.5k | if (out_abs == NULL) |
304 | 0 | goto err; |
305 | | |
306 | 42.5k | if (*out_abs != NULL) { |
307 | 24.3k | ASN1_BIT_STRING_free(*out_abs); |
308 | 24.3k | *out_abs = NULL; |
309 | 24.3k | } |
310 | | |
311 | 42.5k | if (!CBS_get_u8(cbs, &unused_bits)) { |
312 | 1 | ASN1error(ASN1_R_STRING_TOO_SHORT); |
313 | 1 | goto err; |
314 | 1 | } |
315 | | |
316 | 42.5k | if (!CBS_stow(cbs, &data, &data_len)) |
317 | 0 | goto err; |
318 | 42.5k | if (data_len > INT_MAX) |
319 | 0 | goto err; |
320 | | |
321 | 42.5k | if ((abs = ASN1_BIT_STRING_new()) == NULL) |
322 | 0 | goto err; |
323 | | |
324 | 42.5k | abs->data = data; |
325 | 42.5k | abs->length = (int)data_len; |
326 | 42.5k | data = NULL; |
327 | | |
328 | | /* |
329 | | * We do this to preserve the settings. If we modify the settings, |
330 | | * via the _set_bit function, we will recalculate on output. |
331 | | */ |
332 | 42.5k | if (!asn1_abs_set_unused_bits(abs, unused_bits)) { |
333 | 6 | ASN1error(ASN1_R_INVALID_BIT_STRING_BITS_LEFT); |
334 | 6 | goto err; |
335 | 6 | } |
336 | 42.5k | if (abs->length > 0) |
337 | 42.5k | abs->data[abs->length - 1] &= 0xff << unused_bits; |
338 | | |
339 | 42.5k | *out_abs = abs; |
340 | 42.5k | abs = NULL; |
341 | | |
342 | 42.5k | ret = 1; |
343 | | |
344 | 42.5k | err: |
345 | 42.5k | ASN1_BIT_STRING_free(abs); |
346 | 42.5k | freezero(data, data_len); |
347 | | |
348 | 42.5k | return ret; |
349 | 42.5k | } |
350 | | |
351 | | ASN1_BIT_STRING * |
352 | | c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **out_abs, const unsigned char **pp, long len) |
353 | 0 | { |
354 | 0 | ASN1_BIT_STRING *abs = NULL; |
355 | 0 | CBS content; |
356 | |
|
357 | 0 | if (out_abs != NULL) { |
358 | 0 | ASN1_BIT_STRING_free(*out_abs); |
359 | 0 | *out_abs = NULL; |
360 | 0 | } |
361 | |
|
362 | 0 | if (len < 0) { |
363 | 0 | ASN1error(ASN1_R_LENGTH_ERROR); |
364 | 0 | return NULL; |
365 | 0 | } |
366 | | |
367 | 0 | CBS_init(&content, *pp, len); |
368 | |
|
369 | 0 | if (!c2i_ASN1_BIT_STRING_cbs(&abs, &content)) |
370 | 0 | return NULL; |
371 | | |
372 | 0 | *pp = CBS_data(&content); |
373 | |
|
374 | 0 | if (out_abs != NULL) |
375 | 0 | *out_abs = abs; |
376 | |
|
377 | 0 | return abs; |
378 | 0 | } |
379 | | |
380 | | int |
381 | | i2d_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **out) |
382 | 0 | { |
383 | 0 | return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_BIT_STRING_it); |
384 | 0 | } |
385 | | |
386 | | ASN1_BIT_STRING * |
387 | | d2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, const unsigned char **in, long len) |
388 | 0 | { |
389 | 0 | return (ASN1_BIT_STRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, |
390 | 0 | &ASN1_BIT_STRING_it); |
391 | 0 | } |