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