xref: /openbsd-src/lib/libcrypto/asn1/a_bitstr.c (revision 71d0c207ee7b061d5c1e0407b4178f28832e48d0)
1 /* $OpenBSD: a_bitstr.c,v 1.33 2021/12/25 08:52:44 jsing 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 <stdio.h>
60 #include <string.h>
61 
62 #include <openssl/asn1.h>
63 #include <openssl/asn1t.h>
64 #include <openssl/conf.h>
65 #include <openssl/err.h>
66 #include <openssl/x509v3.h>
67 
68 const ASN1_ITEM ASN1_BIT_STRING_it = {
69 	.itype = ASN1_ITYPE_PRIMITIVE,
70 	.utype = V_ASN1_BIT_STRING,
71 	.sname = "ASN1_BIT_STRING",
72 };
73 
74 ASN1_BIT_STRING *
75 ASN1_BIT_STRING_new(void)
76 {
77 	return (ASN1_BIT_STRING *)ASN1_item_new(&ASN1_BIT_STRING_it);
78 }
79 
80 void
81 ASN1_BIT_STRING_free(ASN1_BIT_STRING *a)
82 {
83 	ASN1_item_free((ASN1_VALUE *)a, &ASN1_BIT_STRING_it);
84 }
85 
86 int
87 ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len)
88 {
89 	return ASN1_STRING_set(x, d, len);
90 }
91 
92 int
93 ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value)
94 {
95 	int w, v, iv;
96 	unsigned char *c;
97 
98 	w = n/8;
99 	v = 1 << (7 - (n & 0x07));
100 	iv = ~v;
101 	if (!value)
102 		v = 0;
103 
104 	if (a == NULL)
105 		return 0;
106 
107 	a->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear, set on write */
108 
109 	if ((a->length < (w + 1)) || (a->data == NULL)) {
110 		if (!value)
111 			return(1); /* Don't need to set */
112 		if ((c = recallocarray(a->data, a->length, w + 1, 1)) == NULL) {
113 			ASN1error(ERR_R_MALLOC_FAILURE);
114 			return 0;
115 		}
116 		a->data = c;
117 		a->length = w + 1;
118 	}
119 	a->data[w] = ((a->data[w]) & iv) | v;
120 	while ((a->length > 0) && (a->data[a->length - 1] == 0))
121 		a->length--;
122 
123 	return (1);
124 }
125 
126 int
127 ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *a, int n)
128 {
129 	int w, v;
130 
131 	w = n / 8;
132 	v = 1 << (7 - (n & 0x07));
133 	if ((a == NULL) || (a->length < (w + 1)) || (a->data == NULL))
134 		return (0);
135 	return ((a->data[w] & v) != 0);
136 }
137 
138 /*
139  * Checks if the given bit string contains only bits specified by
140  * the flags vector. Returns 0 if there is at least one bit set in 'a'
141  * which is not specified in 'flags', 1 otherwise.
142  * 'len' is the length of 'flags'.
143  */
144 int
145 ASN1_BIT_STRING_check(const ASN1_BIT_STRING *a, const unsigned char *flags,
146     int flags_len)
147 {
148 	int i, ok;
149 
150 	/* Check if there is one bit set at all. */
151 	if (!a || !a->data)
152 		return 1;
153 
154 	/* Check each byte of the internal representation of the bit string. */
155 	ok = 1;
156 	for (i = 0; i < a->length && ok; ++i) {
157 		unsigned char mask = i < flags_len ? ~flags[i] : 0xff;
158 		/* We are done if there is an unneeded bit set. */
159 		ok = (a->data[i] & mask) == 0;
160 	}
161 	return ok;
162 }
163 
164 int
165 ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs,
166     BIT_STRING_BITNAME *tbl, int indent)
167 {
168 	BIT_STRING_BITNAME *bnam;
169 	char first = 1;
170 
171 	BIO_printf(out, "%*s", indent, "");
172 	for (bnam = tbl; bnam->lname; bnam++) {
173 		if (ASN1_BIT_STRING_get_bit(bs, bnam->bitnum)) {
174 			if (!first)
175 				BIO_puts(out, ", ");
176 			BIO_puts(out, bnam->lname);
177 			first = 0;
178 		}
179 	}
180 	BIO_puts(out, "\n");
181 	return 1;
182 }
183 
184 int
185 ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, const char *name, int value,
186     BIT_STRING_BITNAME *tbl)
187 {
188 	int bitnum;
189 
190 	bitnum = ASN1_BIT_STRING_num_asc(name, tbl);
191 	if (bitnum < 0)
192 		return 0;
193 	if (bs) {
194 		if (!ASN1_BIT_STRING_set_bit(bs, bitnum, value))
195 			return 0;
196 	}
197 	return 1;
198 }
199 
200 int
201 ASN1_BIT_STRING_num_asc(const char *name, BIT_STRING_BITNAME *tbl)
202 {
203 	BIT_STRING_BITNAME *bnam;
204 
205 	for (bnam = tbl; bnam->lname; bnam++) {
206 		if (!strcmp(bnam->sname, name) ||
207 		    !strcmp(bnam->lname, name))
208 			return bnam->bitnum;
209 	}
210 	return -1;
211 }
212 
213 int
214 i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp)
215 {
216 	int ret, j, bits, len;
217 	unsigned char *p, *d;
218 
219 	if (a == NULL)
220 		return (0);
221 
222 	len = a->length;
223 
224 	if (len > 0) {
225 		if (a->flags & ASN1_STRING_FLAG_BITS_LEFT) {
226 			bits = (int)a->flags & 0x07;
227 		} else {
228 			for (; len > 0; len--) {
229 				if (a->data[len - 1])
230 					break;
231 			}
232 			j = a->data[len - 1];
233 			if (j & 0x01)
234 				bits = 0;
235 			else if (j & 0x02)
236 				bits = 1;
237 			else if (j & 0x04)
238 				bits = 2;
239 			else if (j & 0x08)
240 				bits = 3;
241 			else if (j & 0x10)
242 				bits = 4;
243 			else if (j & 0x20)
244 				bits = 5;
245 			else if (j & 0x40)
246 				bits = 6;
247 			else if (j & 0x80)
248 				bits = 7;
249 			else
250 				bits = 0; /* should not happen */
251 		}
252 	} else
253 		bits = 0;
254 
255 	ret = 1 + len;
256 	if (pp == NULL)
257 		return (ret);
258 
259 	p= *pp;
260 
261 	*(p++) = (unsigned char)bits;
262 	d = a->data;
263 	if (len > 0) {
264 		memcpy(p, d, len);
265 		p += len;
266 		p[-1] &= 0xff << bits;
267 	}
268 	*pp = p;
269 	return (ret);
270 }
271 
272 ASN1_BIT_STRING *
273 c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, const unsigned char **pp, long len)
274 {
275 	ASN1_BIT_STRING *ret = NULL;
276 	const unsigned char *p;
277 	unsigned char *s;
278 	int i;
279 
280 	if (len < 1) {
281 		ASN1error(ASN1_R_STRING_TOO_SHORT);
282 		goto err;
283 	}
284 
285 	if (a == NULL || *a == NULL) {
286 		if ((ret = ASN1_BIT_STRING_new()) == NULL)
287 			return (NULL);
288 	} else
289 		ret = *a;
290 
291 	p = *pp;
292 	i = *(p++);
293 	if (i > 7) {
294 		ASN1error(ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
295 		goto err;
296 	}
297 
298 	/*
299 	 * We do this to preserve the settings. If we modify the settings,
300 	 * via the _set_bit function, we will recalculate on output.
301 	 */
302 	ret->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear */
303 	ret->flags |= (ASN1_STRING_FLAG_BITS_LEFT | i); /* set */
304 
305 	/* using one because of the bits left byte */
306 	if (len-- > 1) {
307 		if ((s = malloc(len)) == NULL) {
308 			ASN1error(ERR_R_MALLOC_FAILURE);
309 			goto err;
310 		}
311 		memcpy(s, p, len);
312 		s[len - 1] &= (0xff << i);
313 		p += len;
314 	} else
315 		s = NULL;
316 
317 	free(ret->data);
318 	ret->data = s;
319 	ret->length = (int)len;
320 	ret->type = V_ASN1_BIT_STRING;
321 
322 	if (a != NULL)
323 		*a = ret;
324 
325 	*pp = p;
326 
327 	return (ret);
328 
329  err:
330 	if (a == NULL || *a != ret)
331 		ASN1_BIT_STRING_free(ret);
332 
333 	return (NULL);
334 }
335 
336 int
337 i2d_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **out)
338 {
339 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_BIT_STRING_it);
340 }
341 
342 ASN1_BIT_STRING *
343 d2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, const unsigned char **in, long len)
344 {
345 	return (ASN1_BIT_STRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
346 	    &ASN1_BIT_STRING_it);
347 }
348