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