xref: /openbsd/lib/libcrypto/asn1/a_bitstr.c (revision 7523ec26)
1 /* $OpenBSD: a_bitstr.c,v 1.43 2024/07/08 14:52:31 beck 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 LCRYPTO_ALIAS(ASN1_BIT_STRING_it);
77 
78 ASN1_BIT_STRING *
ASN1_BIT_STRING_new(void)79 ASN1_BIT_STRING_new(void)
80 {
81 	return (ASN1_BIT_STRING *)ASN1_item_new(&ASN1_BIT_STRING_it);
82 }
83 LCRYPTO_ALIAS(ASN1_BIT_STRING_new);
84 
85 void
ASN1_BIT_STRING_free(ASN1_BIT_STRING * a)86 ASN1_BIT_STRING_free(ASN1_BIT_STRING *a)
87 {
88 	ASN1_item_free((ASN1_VALUE *)a, &ASN1_BIT_STRING_it);
89 }
90 LCRYPTO_ALIAS(ASN1_BIT_STRING_free);
91 
92 static void
asn1_abs_clear_unused_bits(ASN1_BIT_STRING * abs)93 asn1_abs_clear_unused_bits(ASN1_BIT_STRING *abs)
94 {
95 	abs->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
96 }
97 
98 int
asn1_abs_set_unused_bits(ASN1_BIT_STRING * abs,uint8_t unused_bits)99 asn1_abs_set_unused_bits(ASN1_BIT_STRING *abs, uint8_t unused_bits)
100 {
101 	if (unused_bits > 7)
102 		return 0;
103 
104 	asn1_abs_clear_unused_bits(abs);
105 
106 	abs->flags |= ASN1_STRING_FLAG_BITS_LEFT | unused_bits;
107 
108 	return 1;
109 }
110 
111 int
ASN1_BIT_STRING_set(ASN1_BIT_STRING * x,unsigned char * d,int len)112 ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len)
113 {
114 	return ASN1_STRING_set(x, d, len);
115 }
116 LCRYPTO_ALIAS(ASN1_BIT_STRING_set);
117 
118 int
ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING * a,int n,int value)119 ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value)
120 {
121 	int w, v, iv;
122 	unsigned char *c;
123 
124 	if (a == NULL)
125 		return 0;
126 	if (n < 0)
127 		return 0;
128 
129 	w = n / 8;
130 	v = 1 << (7 - (n & 0x07));
131 	iv = ~v;
132 
133 	if (value == 0)
134 		v = 0;
135 
136 	asn1_abs_clear_unused_bits(a);
137 
138 	if (a->length < w + 1 || a->data == NULL) {
139 		/* Don't expand if there's no bit to set. */
140 		if (value == 0)
141 			return 1;
142 		if ((c = recallocarray(a->data, a->length, w + 1, 1)) == NULL) {
143 			ASN1error(ERR_R_MALLOC_FAILURE);
144 			return 0;
145 		}
146 		a->data = c;
147 		a->length = w + 1;
148 	}
149 
150 	a->data[w] = ((a->data[w]) & iv) | v;
151 	while (a->length > 0 && a->data[a->length - 1] == 0)
152 		a->length--;
153 
154 	return 1;
155 }
156 LCRYPTO_ALIAS(ASN1_BIT_STRING_set_bit);
157 
158 int
ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING * a,int n)159 ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *a, int n)
160 {
161 	int w, v;
162 
163 	if (a == NULL)
164 		return 0;
165 	if (n < 0)
166 		return 0;
167 
168 	w = n / 8;
169 	v = 1 << (7 - (n & 0x07));
170 
171 	if (a->length < w + 1 || a->data == NULL)
172 		return 0;
173 
174 	return (a->data[w] & v) != 0;
175 }
176 LCRYPTO_ALIAS(ASN1_BIT_STRING_get_bit);
177 
178 int
i2c_ASN1_BIT_STRING(ASN1_BIT_STRING * a,unsigned char ** pp)179 i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp)
180 {
181 	int ret, j, bits, len;
182 	unsigned char *p, *d;
183 
184 	if (a == NULL)
185 		return (0);
186 
187 	if (a->length == INT_MAX)
188 		return (0);
189 
190 	ret = a->length + 1;
191 
192 	if (pp == NULL)
193 		return (ret);
194 
195 	len = a->length;
196 
197 	if (len > 0) {
198 		if (a->flags & ASN1_STRING_FLAG_BITS_LEFT) {
199 			bits = (int)a->flags & 0x07;
200 		} else {
201 			j = 0;
202 			for (; len > 0; len--) {
203 				if (a->data[len - 1])
204 					break;
205 			}
206 			if (len > 0)
207 				j = a->data[len - 1];
208 			if (j & 0x01)
209 				bits = 0;
210 			else if (j & 0x02)
211 				bits = 1;
212 			else if (j & 0x04)
213 				bits = 2;
214 			else if (j & 0x08)
215 				bits = 3;
216 			else if (j & 0x10)
217 				bits = 4;
218 			else if (j & 0x20)
219 				bits = 5;
220 			else if (j & 0x40)
221 				bits = 6;
222 			else if (j & 0x80)
223 				bits = 7;
224 			else
225 				bits = 0; /* should not happen */
226 		}
227 	} else
228 		bits = 0;
229 
230 	p= *pp;
231 
232 	*(p++) = (unsigned char)bits;
233 	d = a->data;
234 	if (len > 0) {
235 		memcpy(p, d, len);
236 		p += len;
237 		p[-1] &= 0xff << bits;
238 	}
239 	*pp = p;
240 	return (ret);
241 }
242 
243 int
c2i_ASN1_BIT_STRING_cbs(ASN1_BIT_STRING ** out_abs,CBS * cbs)244 c2i_ASN1_BIT_STRING_cbs(ASN1_BIT_STRING **out_abs, CBS *cbs)
245 {
246 	ASN1_BIT_STRING *abs = NULL;
247 	uint8_t *data = NULL;
248 	size_t data_len = 0;
249 	uint8_t unused_bits;
250 	int ret = 0;
251 
252 	if (out_abs == NULL)
253 		goto err;
254 
255 	if (*out_abs != NULL) {
256 		ASN1_BIT_STRING_free(*out_abs);
257 		*out_abs = NULL;
258 	}
259 
260 	if (!CBS_get_u8(cbs, &unused_bits)) {
261 		ASN1error(ASN1_R_STRING_TOO_SHORT);
262 		goto err;
263 	}
264 
265 	if (!CBS_stow(cbs, &data, &data_len))
266 		goto err;
267 	if (data_len > INT_MAX)
268 		goto err;
269 
270 	if ((abs = ASN1_BIT_STRING_new()) == NULL)
271 		goto err;
272 
273 	abs->data = data;
274 	abs->length = (int)data_len;
275 	data = NULL;
276 
277 	/*
278 	 * We do this to preserve the settings. If we modify the settings,
279 	 * via the _set_bit function, we will recalculate on output.
280 	 */
281 	if (!asn1_abs_set_unused_bits(abs, unused_bits)) {
282 		ASN1error(ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
283 		goto err;
284 	}
285 	if (abs->length > 0)
286 		abs->data[abs->length - 1] &= 0xff << unused_bits;
287 
288 	*out_abs = abs;
289 	abs = NULL;
290 
291 	ret = 1;
292 
293  err:
294 	ASN1_BIT_STRING_free(abs);
295 	freezero(data, data_len);
296 
297 	return ret;
298 }
299 
300 ASN1_BIT_STRING *
c2i_ASN1_BIT_STRING(ASN1_BIT_STRING ** out_abs,const unsigned char ** pp,long len)301 c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **out_abs, const unsigned char **pp, long len)
302 {
303 	ASN1_BIT_STRING *abs = NULL;
304 	CBS content;
305 
306 	if (out_abs != NULL) {
307 		ASN1_BIT_STRING_free(*out_abs);
308 		*out_abs = NULL;
309 	}
310 
311 	if (len < 0) {
312 		ASN1error(ASN1_R_LENGTH_ERROR);
313 		return NULL;
314 	}
315 
316 	CBS_init(&content, *pp, len);
317 
318 	if (!c2i_ASN1_BIT_STRING_cbs(&abs, &content))
319 		return NULL;
320 
321 	*pp = CBS_data(&content);
322 
323 	if (out_abs != NULL)
324 		*out_abs = abs;
325 
326 	return abs;
327 }
328 
329 int
i2d_ASN1_BIT_STRING(ASN1_BIT_STRING * a,unsigned char ** out)330 i2d_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **out)
331 {
332 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_BIT_STRING_it);
333 }
334 LCRYPTO_ALIAS(i2d_ASN1_BIT_STRING);
335 
336 ASN1_BIT_STRING *
d2i_ASN1_BIT_STRING(ASN1_BIT_STRING ** a,const unsigned char ** in,long len)337 d2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, const unsigned char **in, long len)
338 {
339 	return (ASN1_BIT_STRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
340 	    &ASN1_BIT_STRING_it);
341 }
342 LCRYPTO_ALIAS(d2i_ASN1_BIT_STRING);
343