/src/libressl/crypto/asn1/a_int.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* $OpenBSD: a_int.c,v 1.44 2022/07/13 20:07: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 <limits.h> |
60 | | #include <stdio.h> |
61 | | #include <string.h> |
62 | | |
63 | | #include <openssl/asn1.h> |
64 | | #include <openssl/asn1t.h> |
65 | | #include <openssl/bn.h> |
66 | | #include <openssl/buffer.h> |
67 | | #include <openssl/err.h> |
68 | | |
69 | | #include "bytestring.h" |
70 | | |
71 | | const ASN1_ITEM ASN1_INTEGER_it = { |
72 | | .itype = ASN1_ITYPE_PRIMITIVE, |
73 | | .utype = V_ASN1_INTEGER, |
74 | | .sname = "ASN1_INTEGER", |
75 | | }; |
76 | | |
77 | | ASN1_INTEGER * |
78 | | ASN1_INTEGER_new(void) |
79 | 222k | { |
80 | 222k | return (ASN1_INTEGER *)ASN1_item_new(&ASN1_INTEGER_it); |
81 | 222k | } |
82 | | |
83 | | static void |
84 | | asn1_aint_clear(ASN1_INTEGER *aint) |
85 | 42.0k | { |
86 | 42.0k | freezero(aint->data, aint->length); |
87 | | |
88 | 42.0k | memset(aint, 0, sizeof(*aint)); |
89 | | |
90 | 42.0k | aint->type = V_ASN1_INTEGER; |
91 | 42.0k | } |
92 | | |
93 | | void |
94 | | ASN1_INTEGER_free(ASN1_INTEGER *a) |
95 | 339k | { |
96 | 339k | ASN1_item_free((ASN1_VALUE *)a, &ASN1_INTEGER_it); |
97 | 339k | } |
98 | | |
99 | | static int |
100 | | ASN1_INTEGER_valid(const ASN1_INTEGER *a) |
101 | 436k | { |
102 | 436k | return (a != NULL && a->length >= 0); |
103 | 436k | } |
104 | | |
105 | | ASN1_INTEGER * |
106 | | ASN1_INTEGER_dup(const ASN1_INTEGER *x) |
107 | 0 | { |
108 | 0 | if (!ASN1_INTEGER_valid(x)) |
109 | 0 | return NULL; |
110 | | |
111 | 0 | return ASN1_STRING_dup(x); |
112 | 0 | } |
113 | | |
114 | | int |
115 | | ASN1_INTEGER_cmp(const ASN1_INTEGER *a, const ASN1_INTEGER *b) |
116 | 0 | { |
117 | 0 | int ret = 1; |
118 | | |
119 | | /* Compare sign, then content. */ |
120 | 0 | if ((a->type & V_ASN1_NEG) == (b->type & V_ASN1_NEG)) |
121 | 0 | ret = ASN1_STRING_cmp(a, b); |
122 | |
|
123 | 0 | if ((a->type & V_ASN1_NEG) != 0) |
124 | 0 | return -ret; |
125 | | |
126 | 0 | return ret; |
127 | 0 | } |
128 | | |
129 | | int |
130 | | asn1_aint_get_uint64(CBS *cbs, uint64_t *out_val) |
131 | 45.7k | { |
132 | 45.7k | uint64_t val = 0; |
133 | 45.7k | uint8_t u8; |
134 | | |
135 | 45.7k | *out_val = 0; |
136 | | |
137 | 96.7k | while (CBS_len(cbs) > 0) { |
138 | 51.0k | if (!CBS_get_u8(cbs, &u8)) |
139 | 0 | return 0; |
140 | 51.0k | if (val > (UINT64_MAX >> 8)) { |
141 | 33 | ASN1error(ASN1_R_TOO_LARGE); |
142 | 33 | return 0; |
143 | 33 | } |
144 | 50.9k | val = val << 8 | u8; |
145 | 50.9k | } |
146 | | |
147 | 45.7k | *out_val = val; |
148 | | |
149 | 45.7k | return 1; |
150 | 45.7k | } |
151 | | |
152 | | int |
153 | | asn1_aint_set_uint64(uint64_t val, uint8_t **out_data, int *out_len) |
154 | 42.0k | { |
155 | 42.0k | uint8_t *data = NULL; |
156 | 42.0k | size_t data_len = 0; |
157 | 42.0k | int started = 0; |
158 | 42.0k | uint8_t u8; |
159 | 42.0k | CBB cbb; |
160 | 42.0k | int i; |
161 | 42.0k | int ret = 0; |
162 | | |
163 | 42.0k | if (!CBB_init(&cbb, sizeof(long))) |
164 | 0 | goto err; |
165 | | |
166 | 42.0k | if (out_data == NULL || out_len == NULL) |
167 | 0 | goto err; |
168 | 42.0k | if (*out_data != NULL || *out_len != 0) |
169 | 0 | goto err; |
170 | | |
171 | 378k | for (i = sizeof(uint64_t) - 1; i >= 0; i--) { |
172 | 336k | u8 = (val >> (i * 8)) & 0xff; |
173 | 336k | if (!started && i != 0 && u8 == 0) |
174 | 274k | continue; |
175 | 61.9k | if (!CBB_add_u8(&cbb, u8)) |
176 | 0 | goto err; |
177 | 61.9k | started = 1; |
178 | 61.9k | } |
179 | | |
180 | 42.0k | if (!CBB_finish(&cbb, &data, &data_len)) |
181 | 0 | goto err; |
182 | 42.0k | if (data_len > INT_MAX) |
183 | 0 | goto err; |
184 | | |
185 | 42.0k | *out_data = data; |
186 | 42.0k | *out_len = (int)data_len; |
187 | 42.0k | data = NULL; |
188 | | |
189 | 42.0k | ret = 1; |
190 | 42.0k | err: |
191 | 42.0k | CBB_cleanup(&cbb); |
192 | 42.0k | freezero(data, data_len); |
193 | | |
194 | 42.0k | return ret; |
195 | 42.0k | } |
196 | | |
197 | | int |
198 | | asn1_aint_get_int64(CBS *cbs, int negative, int64_t *out_val) |
199 | 45.7k | { |
200 | 45.7k | uint64_t val; |
201 | | |
202 | 45.7k | if (!asn1_aint_get_uint64(cbs, &val)) |
203 | 33 | return 0; |
204 | | |
205 | 45.7k | if (negative) { |
206 | 3.18k | if (val > (uint64_t)INT64_MIN) { |
207 | 7 | ASN1error(ASN1_R_TOO_SMALL); |
208 | 7 | return 0; |
209 | 7 | } |
210 | 3.17k | *out_val = (int64_t)-val; |
211 | 42.5k | } else { |
212 | 42.5k | if (val > (uint64_t)INT64_MAX) { |
213 | 63 | ASN1error(ASN1_R_TOO_LARGE); |
214 | 63 | return 0; |
215 | 63 | } |
216 | 42.4k | *out_val = (int64_t)val; |
217 | 42.4k | } |
218 | | |
219 | 45.6k | return 1; |
220 | 45.7k | } |
221 | | |
222 | | int |
223 | | ASN1_INTEGER_get_uint64(uint64_t *out_val, const ASN1_INTEGER *aint) |
224 | 0 | { |
225 | 0 | uint64_t val; |
226 | 0 | CBS cbs; |
227 | |
|
228 | 0 | *out_val = 0; |
229 | |
|
230 | 0 | if (aint == NULL || aint->length < 0) |
231 | 0 | return 0; |
232 | | |
233 | 0 | if (aint->type == V_ASN1_NEG_INTEGER) { |
234 | 0 | ASN1error(ASN1_R_ILLEGAL_NEGATIVE_VALUE); |
235 | 0 | return 0; |
236 | 0 | } |
237 | 0 | if (aint->type != V_ASN1_INTEGER) { |
238 | 0 | ASN1error(ASN1_R_WRONG_INTEGER_TYPE); |
239 | 0 | return 0; |
240 | 0 | } |
241 | | |
242 | 0 | CBS_init(&cbs, aint->data, aint->length); |
243 | |
|
244 | 0 | if (!asn1_aint_get_uint64(&cbs, &val)) |
245 | 0 | return 0; |
246 | | |
247 | 0 | *out_val = val; |
248 | |
|
249 | 0 | return 1; |
250 | 0 | } |
251 | | |
252 | | int |
253 | | ASN1_INTEGER_set_uint64(ASN1_INTEGER *aint, uint64_t val) |
254 | 0 | { |
255 | 0 | asn1_aint_clear(aint); |
256 | |
|
257 | 0 | return asn1_aint_set_uint64(val, &aint->data, &aint->length); |
258 | 0 | } |
259 | | |
260 | | int |
261 | | ASN1_INTEGER_get_int64(int64_t *out_val, const ASN1_INTEGER *aint) |
262 | 11.4k | { |
263 | 11.4k | CBS cbs; |
264 | | |
265 | 11.4k | *out_val = 0; |
266 | | |
267 | 11.4k | if (aint == NULL || aint->length < 0) |
268 | 0 | return 0; |
269 | | |
270 | 11.4k | if (aint->type != V_ASN1_INTEGER && |
271 | 11.4k | aint->type != V_ASN1_NEG_INTEGER) { |
272 | 0 | ASN1error(ASN1_R_WRONG_INTEGER_TYPE); |
273 | 0 | return 0; |
274 | 0 | } |
275 | | |
276 | 11.4k | CBS_init(&cbs, aint->data, aint->length); |
277 | | |
278 | 11.4k | return asn1_aint_get_int64(&cbs, (aint->type == V_ASN1_NEG_INTEGER), |
279 | 11.4k | out_val); |
280 | 11.4k | } |
281 | | |
282 | | int |
283 | | ASN1_INTEGER_set_int64(ASN1_INTEGER *aint, int64_t val) |
284 | 42.0k | { |
285 | 42.0k | uint64_t uval; |
286 | | |
287 | 42.0k | asn1_aint_clear(aint); |
288 | | |
289 | 42.0k | uval = (uint64_t)val; |
290 | | |
291 | 42.0k | if (val < 0) { |
292 | 11.5k | aint->type = V_ASN1_NEG_INTEGER; |
293 | 11.5k | uval = -uval; |
294 | 11.5k | } |
295 | | |
296 | 42.0k | return asn1_aint_set_uint64(uval, &aint->data, &aint->length); |
297 | 42.0k | } |
298 | | |
299 | | long |
300 | | ASN1_INTEGER_get(const ASN1_INTEGER *aint) |
301 | 0 | { |
302 | 0 | int64_t val; |
303 | |
|
304 | 0 | if (aint == NULL) |
305 | 0 | return 0; |
306 | 0 | if (!ASN1_INTEGER_get_int64(&val, aint)) |
307 | 0 | return -1; |
308 | 0 | if (val < LONG_MIN || val > LONG_MAX) { |
309 | | /* hmm... a bit ugly, return all ones */ |
310 | 0 | return -1; |
311 | 0 | } |
312 | | |
313 | 0 | return (long)val; |
314 | 0 | } |
315 | | |
316 | | int |
317 | | ASN1_INTEGER_set(ASN1_INTEGER *aint, long val) |
318 | 0 | { |
319 | 0 | return ASN1_INTEGER_set_int64(aint, val); |
320 | 0 | } |
321 | | |
322 | | ASN1_INTEGER * |
323 | | BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai) |
324 | 0 | { |
325 | 0 | ASN1_INTEGER *ret; |
326 | 0 | int len, j; |
327 | |
|
328 | 0 | if (ai == NULL) |
329 | 0 | ret = ASN1_INTEGER_new(); |
330 | 0 | else |
331 | 0 | ret = ai; |
332 | 0 | if (ret == NULL) { |
333 | 0 | ASN1error(ERR_R_NESTED_ASN1_ERROR); |
334 | 0 | goto err; |
335 | 0 | } |
336 | | |
337 | 0 | if (!ASN1_INTEGER_valid(ret)) |
338 | 0 | goto err; |
339 | | |
340 | 0 | if (BN_is_negative(bn)) |
341 | 0 | ret->type = V_ASN1_NEG_INTEGER; |
342 | 0 | else |
343 | 0 | ret->type = V_ASN1_INTEGER; |
344 | 0 | j = BN_num_bits(bn); |
345 | 0 | len = ((j == 0) ? 0 : ((j / 8) + 1)); |
346 | 0 | if (ret->length < len + 4) { |
347 | 0 | unsigned char *new_data = realloc(ret->data, len + 4); |
348 | 0 | if (!new_data) { |
349 | 0 | ASN1error(ERR_R_MALLOC_FAILURE); |
350 | 0 | goto err; |
351 | 0 | } |
352 | 0 | ret->data = new_data; |
353 | 0 | } |
354 | 0 | ret->length = BN_bn2bin(bn, ret->data); |
355 | | |
356 | | /* Correct zero case */ |
357 | 0 | if (!ret->length) { |
358 | 0 | ret->data[0] = 0; |
359 | 0 | ret->length = 1; |
360 | 0 | } |
361 | 0 | return (ret); |
362 | | |
363 | 0 | err: |
364 | 0 | if (ret != ai) |
365 | 0 | ASN1_INTEGER_free(ret); |
366 | 0 | return (NULL); |
367 | 0 | } |
368 | | |
369 | | BIGNUM * |
370 | | ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn) |
371 | 0 | { |
372 | 0 | BIGNUM *ret; |
373 | |
|
374 | 0 | if (!ASN1_INTEGER_valid(ai)) |
375 | 0 | return (NULL); |
376 | | |
377 | 0 | if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL) |
378 | 0 | ASN1error(ASN1_R_BN_LIB); |
379 | 0 | else if (ai->type == V_ASN1_NEG_INTEGER) |
380 | 0 | BN_set_negative(ret, 1); |
381 | 0 | return (ret); |
382 | 0 | } |
383 | | |
384 | | int |
385 | | i2a_ASN1_INTEGER(BIO *bp, const ASN1_INTEGER *a) |
386 | 0 | { |
387 | 0 | int i, n = 0; |
388 | 0 | static const char h[] = "0123456789ABCDEF"; |
389 | 0 | char buf[2]; |
390 | |
|
391 | 0 | if (a == NULL) |
392 | 0 | return (0); |
393 | | |
394 | 0 | if (a->type & V_ASN1_NEG) { |
395 | 0 | if (BIO_write(bp, "-", 1) != 1) |
396 | 0 | goto err; |
397 | 0 | n = 1; |
398 | 0 | } |
399 | | |
400 | 0 | if (a->length == 0) { |
401 | 0 | if (BIO_write(bp, "00", 2) != 2) |
402 | 0 | goto err; |
403 | 0 | n += 2; |
404 | 0 | } else { |
405 | 0 | for (i = 0; i < a->length; i++) { |
406 | 0 | if ((i != 0) && (i % 35 == 0)) { |
407 | 0 | if (BIO_write(bp, "\\\n", 2) != 2) |
408 | 0 | goto err; |
409 | 0 | n += 2; |
410 | 0 | } |
411 | 0 | buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f]; |
412 | 0 | buf[1] = h[((unsigned char)a->data[i]) & 0x0f]; |
413 | 0 | if (BIO_write(bp, buf, 2) != 2) |
414 | 0 | goto err; |
415 | 0 | n += 2; |
416 | 0 | } |
417 | 0 | } |
418 | 0 | return (n); |
419 | | |
420 | 0 | err: |
421 | 0 | return (-1); |
422 | 0 | } |
423 | | |
424 | | int |
425 | | a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size) |
426 | 0 | { |
427 | 0 | int ret = 0; |
428 | 0 | int i, j,k, m,n, again, bufsize; |
429 | 0 | unsigned char *s = NULL, *sp; |
430 | 0 | unsigned char *bufp; |
431 | 0 | int num = 0, slen = 0, first = 1; |
432 | |
|
433 | 0 | bs->type = V_ASN1_INTEGER; |
434 | |
|
435 | 0 | bufsize = BIO_gets(bp, buf, size); |
436 | 0 | for (;;) { |
437 | 0 | if (bufsize < 1) |
438 | 0 | goto err_sl; |
439 | 0 | i = bufsize; |
440 | 0 | if (buf[i - 1] == '\n') |
441 | 0 | buf[--i] = '\0'; |
442 | 0 | if (i == 0) |
443 | 0 | goto err_sl; |
444 | 0 | if (buf[i - 1] == '\r') |
445 | 0 | buf[--i] = '\0'; |
446 | 0 | if (i == 0) |
447 | 0 | goto err_sl; |
448 | 0 | if (buf[i - 1] == '\\') { |
449 | 0 | i--; |
450 | 0 | again = 1; |
451 | 0 | } else |
452 | 0 | again = 0; |
453 | 0 | buf[i] = '\0'; |
454 | 0 | if (i < 2) |
455 | 0 | goto err_sl; |
456 | | |
457 | 0 | bufp = (unsigned char *)buf; |
458 | 0 | if (first) { |
459 | 0 | first = 0; |
460 | 0 | if ((bufp[0] == '0') && (buf[1] == '0')) { |
461 | 0 | bufp += 2; |
462 | 0 | i -= 2; |
463 | 0 | } |
464 | 0 | } |
465 | 0 | k = 0; |
466 | 0 | if (i % 2 != 0) { |
467 | 0 | ASN1error(ASN1_R_ODD_NUMBER_OF_CHARS); |
468 | 0 | goto err; |
469 | 0 | } |
470 | 0 | i /= 2; |
471 | 0 | if (num + i > slen) { |
472 | 0 | if ((sp = recallocarray(s, slen, num + i, 1)) == NULL) { |
473 | 0 | ASN1error(ERR_R_MALLOC_FAILURE); |
474 | 0 | goto err; |
475 | 0 | } |
476 | 0 | s = sp; |
477 | 0 | slen = num + i; |
478 | 0 | } |
479 | 0 | for (j = 0; j < i; j++, k += 2) { |
480 | 0 | for (n = 0; n < 2; n++) { |
481 | 0 | m = bufp[k + n]; |
482 | 0 | if ((m >= '0') && (m <= '9')) |
483 | 0 | m -= '0'; |
484 | 0 | else if ((m >= 'a') && (m <= 'f')) |
485 | 0 | m = m - 'a' + 10; |
486 | 0 | else if ((m >= 'A') && (m <= 'F')) |
487 | 0 | m = m - 'A' + 10; |
488 | 0 | else { |
489 | 0 | ASN1error(ASN1_R_NON_HEX_CHARACTERS); |
490 | 0 | goto err; |
491 | 0 | } |
492 | 0 | s[num + j] <<= 4; |
493 | 0 | s[num + j] |= m; |
494 | 0 | } |
495 | 0 | } |
496 | 0 | num += i; |
497 | 0 | if (again) |
498 | 0 | bufsize = BIO_gets(bp, buf, size); |
499 | 0 | else |
500 | 0 | break; |
501 | 0 | } |
502 | 0 | bs->length = num; |
503 | 0 | bs->data = s; |
504 | 0 | return (1); |
505 | | |
506 | 0 | err_sl: |
507 | 0 | ASN1error(ASN1_R_SHORT_LINE); |
508 | 0 | err: |
509 | 0 | free(s); |
510 | 0 | return (ret); |
511 | 0 | } |
512 | | |
513 | | /* |
514 | | * This converts an ASN1 INTEGER into its content encoding. |
515 | | * The internal representation is an ASN1_STRING whose data is a big endian |
516 | | * representation of the value, ignoring the sign. The sign is determined by |
517 | | * the type: V_ASN1_INTEGER for positive and V_ASN1_NEG_INTEGER for negative. |
518 | | * |
519 | | * Positive integers are no problem: they are almost the same as the DER |
520 | | * encoding, except if the first byte is >= 0x80 we need to add a zero pad. |
521 | | * |
522 | | * Negative integers are a bit trickier... |
523 | | * The DER representation of negative integers is in 2s complement form. |
524 | | * The internal form is converted by complementing each octet and finally |
525 | | * adding one to the result. This can be done less messily with a little trick. |
526 | | * If the internal form has trailing zeroes then they will become FF by the |
527 | | * complement and 0 by the add one (due to carry) so just copy as many trailing |
528 | | * zeros to the destination as there are in the source. The carry will add one |
529 | | * to the last none zero octet: so complement this octet and add one and finally |
530 | | * complement any left over until you get to the start of the string. |
531 | | * |
532 | | * Padding is a little trickier too. If the first bytes is > 0x80 then we pad |
533 | | * with 0xff. However if the first byte is 0x80 and one of the following bytes |
534 | | * is non-zero we pad with 0xff. The reason for this distinction is that 0x80 |
535 | | * followed by optional zeros isn't padded. |
536 | | */ |
537 | | |
538 | | int |
539 | | i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp) |
540 | 436k | { |
541 | 436k | int pad = 0, ret, i, neg; |
542 | 436k | unsigned char *p, *n, pb = 0; |
543 | | |
544 | 436k | if (!ASN1_INTEGER_valid(a)) |
545 | 0 | return 0; |
546 | | |
547 | 436k | neg = a->type & V_ASN1_NEG; |
548 | 436k | if (a->length == 0) |
549 | 0 | ret = 1; |
550 | 436k | else { |
551 | 436k | ret = a->length; |
552 | 436k | i = a->data[0]; |
553 | 436k | if (!neg && (i > 127)) { |
554 | 5.70k | pad = 1; |
555 | 5.70k | pb = 0; |
556 | 430k | } else if (neg) { |
557 | 372k | if (i > 128) { |
558 | 21.5k | pad = 1; |
559 | 21.5k | pb = 0xFF; |
560 | 351k | } else if (i == 128) { |
561 | | /* |
562 | | * Special case: if any other bytes non zero we pad: |
563 | | * otherwise we don't. |
564 | | */ |
565 | 21.2k | for (i = 1; i < a->length; i++) if (a->data[i]) { |
566 | 4.71k | pad = 1; |
567 | 4.71k | pb = 0xFF; |
568 | 4.71k | break; |
569 | 4.71k | } |
570 | 13.3k | } |
571 | 372k | } |
572 | 436k | ret += pad; |
573 | 436k | } |
574 | 436k | if (pp == NULL) |
575 | 387k | return (ret); |
576 | 49.2k | p= *pp; |
577 | | |
578 | 49.2k | if (pad) |
579 | 3.59k | *(p++) = pb; |
580 | 49.2k | if (a->length == 0) |
581 | 0 | *(p++) = 0; |
582 | 49.2k | else if (!neg) |
583 | 7.64k | memcpy(p, a->data, a->length); |
584 | 41.6k | else { |
585 | | /* Begin at the end of the encoding */ |
586 | 41.6k | n = a->data + a->length - 1; |
587 | 41.6k | p += a->length - 1; |
588 | 41.6k | i = a->length; |
589 | | /* Copy zeros to destination as long as source is zero */ |
590 | 46.2k | while (!*n) { |
591 | 4.62k | *(p--) = 0; |
592 | 4.62k | n--; |
593 | 4.62k | i--; |
594 | 4.62k | } |
595 | | /* Complement and increment next octet */ |
596 | 41.6k | *(p--) = ((*(n--)) ^ 0xff) + 1; |
597 | 41.6k | i--; |
598 | | /* Complement any octets left */ |
599 | 9.82M | for (; i > 0; i--) |
600 | 9.78M | *(p--) = *(n--) ^ 0xff; |
601 | 41.6k | } |
602 | | |
603 | 49.2k | *pp += ret; |
604 | 49.2k | return (ret); |
605 | 436k | } |
606 | | |
607 | | static void |
608 | | asn1_aint_twos_complement(uint8_t *data, size_t data_len) |
609 | 49.6k | { |
610 | 49.6k | uint8_t carry = 1; |
611 | 49.6k | ssize_t i; |
612 | | |
613 | 10.9M | for (i = data_len - 1; i >= 0; i--) { |
614 | 10.8M | data[i] = (data[i] ^ 0xff) + carry; |
615 | 10.8M | if (data[i] != 0) |
616 | 10.8M | carry = 0; |
617 | 10.8M | } |
618 | 49.6k | } |
619 | | |
620 | | static int |
621 | | asn1_aint_keep_twos_padding(const uint8_t *data, size_t data_len) |
622 | 37.0k | { |
623 | 37.0k | size_t i; |
624 | | |
625 | | /* |
626 | | * If a two's complement value has a padding byte (0xff) and the rest |
627 | | * of the value is all zeros, the padding byte cannot be removed as when |
628 | | * converted from two's complement this becomes 0x01 (in the place of |
629 | | * the padding byte) followed by the same number of zero bytes. |
630 | | */ |
631 | 37.0k | if (data_len <= 1 || data[0] != 0xff) |
632 | 28.0k | return 0; |
633 | 10.8k | for (i = 1; i < data_len; i++) { |
634 | 9.53k | if (data[i] != 0) |
635 | 7.59k | return 0; |
636 | 9.53k | } |
637 | 1.32k | return 1; |
638 | 8.91k | } |
639 | | |
640 | | int |
641 | | c2i_ASN1_INTEGER_cbs(ASN1_INTEGER **out_aint, CBS *cbs) |
642 | 180k | { |
643 | 180k | ASN1_INTEGER *aint = NULL; |
644 | 180k | uint8_t *data = NULL; |
645 | 180k | size_t data_len = 0; |
646 | 180k | uint8_t padding, val; |
647 | 180k | uint8_t negative = 0; |
648 | 180k | int ret = 0; |
649 | | |
650 | 180k | if (out_aint == NULL) |
651 | 0 | goto err; |
652 | | |
653 | 180k | if (*out_aint != NULL) { |
654 | 82.3k | ASN1_INTEGER_free(*out_aint); |
655 | 82.3k | *out_aint = NULL; |
656 | 82.3k | } |
657 | | |
658 | 180k | if (CBS_len(cbs) == 0) { |
659 | | /* XXX INVALID ENCODING? */ |
660 | 50 | ASN1error(ERR_R_ASN1_LENGTH_MISMATCH); |
661 | 50 | goto err; |
662 | 50 | } |
663 | 180k | if (!CBS_peek_u8(cbs, &val)) |
664 | 0 | goto err; |
665 | | |
666 | | /* Top most bit indicates sign, padding is all zeros or all ones. */ |
667 | 180k | negative = (val >> 7); |
668 | 180k | padding = ~(negative - 1) & 0xff; |
669 | | |
670 | | /* |
671 | | * Ensure that the first 9 bits are not all zero or all one, as per |
672 | | * X.690 section 8.3.2. Remove the padding octet if possible. |
673 | | */ |
674 | 180k | if (CBS_len(cbs) > 1 && val == padding) { |
675 | 37.0k | if (!asn1_aint_keep_twos_padding(CBS_data(cbs), CBS_len(cbs))) { |
676 | 35.6k | if (!CBS_get_u8(cbs, &padding)) |
677 | 0 | goto err; |
678 | 35.6k | if (!CBS_peek_u8(cbs, &val)) |
679 | 0 | goto err; |
680 | 35.6k | if ((val >> 7) == (padding >> 7)) { |
681 | | /* XXX INVALID ENCODING? */ |
682 | 25 | ASN1error(ERR_R_ASN1_LENGTH_MISMATCH); |
683 | 25 | goto err; |
684 | 25 | } |
685 | 35.6k | } |
686 | 37.0k | } |
687 | | |
688 | 180k | if (!CBS_stow(cbs, &data, &data_len)) |
689 | 0 | goto err; |
690 | 180k | if (data_len > INT_MAX) |
691 | 0 | goto err; |
692 | | |
693 | 180k | if ((aint = ASN1_INTEGER_new()) == NULL) |
694 | 0 | goto err; |
695 | | |
696 | | /* |
697 | | * Negative integers are handled as a separate type - convert from |
698 | | * two's complement for internal representation. |
699 | | */ |
700 | 180k | if (negative) { |
701 | 49.6k | aint->type = V_ASN1_NEG_INTEGER; |
702 | 49.6k | asn1_aint_twos_complement(data, data_len); |
703 | 49.6k | } |
704 | | |
705 | 180k | aint->data = data; |
706 | 180k | aint->length = (int)data_len; |
707 | 180k | data = NULL; |
708 | | |
709 | 180k | *out_aint = aint; |
710 | 180k | aint = NULL; |
711 | | |
712 | 180k | ret = 1; |
713 | | |
714 | 180k | err: |
715 | 180k | ASN1_INTEGER_free(aint); |
716 | 180k | freezero(data, data_len); |
717 | | |
718 | 180k | return ret; |
719 | 180k | } |
720 | | |
721 | | ASN1_INTEGER * |
722 | | c2i_ASN1_INTEGER(ASN1_INTEGER **out_aint, const unsigned char **pp, long len) |
723 | 11.4k | { |
724 | 11.4k | ASN1_INTEGER *aint = NULL; |
725 | 11.4k | CBS content; |
726 | | |
727 | 11.4k | if (out_aint != NULL) { |
728 | 11.4k | ASN1_INTEGER_free(*out_aint); |
729 | 11.4k | *out_aint = NULL; |
730 | 11.4k | } |
731 | | |
732 | 11.4k | if (len < 0) { |
733 | 0 | ASN1error(ASN1_R_LENGTH_ERROR); |
734 | 0 | return NULL; |
735 | 0 | } |
736 | | |
737 | 11.4k | CBS_init(&content, *pp, len); |
738 | | |
739 | 11.4k | if (!c2i_ASN1_INTEGER_cbs(&aint, &content)) |
740 | 3 | return NULL; |
741 | | |
742 | 11.4k | *pp = CBS_data(&content); |
743 | | |
744 | 11.4k | if (out_aint != NULL) |
745 | 11.4k | *out_aint = aint; |
746 | | |
747 | 11.4k | return aint; |
748 | 11.4k | } |
749 | | |
750 | | int |
751 | | i2d_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **out) |
752 | 0 | { |
753 | 0 | return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_INTEGER_it); |
754 | 0 | } |
755 | | |
756 | | ASN1_INTEGER * |
757 | | d2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **in, long len) |
758 | 0 | { |
759 | 0 | return (ASN1_INTEGER *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, |
760 | 0 | &ASN1_INTEGER_it); |
761 | 0 | } |
762 | | |
763 | | /* This is a version of d2i_ASN1_INTEGER that ignores the sign bit of |
764 | | * ASN1 integers: some broken software can encode a positive INTEGER |
765 | | * with its MSB set as negative (it doesn't add a padding zero). |
766 | | */ |
767 | | |
768 | | ASN1_INTEGER * |
769 | | d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp, long length) |
770 | 0 | { |
771 | 0 | ASN1_INTEGER *ret = NULL; |
772 | 0 | const unsigned char *p; |
773 | 0 | unsigned char *s; |
774 | 0 | long len; |
775 | 0 | int inf, tag, xclass; |
776 | 0 | int i; |
777 | |
|
778 | 0 | if ((a == NULL) || ((*a) == NULL)) { |
779 | 0 | if ((ret = ASN1_INTEGER_new()) == NULL) |
780 | 0 | return (NULL); |
781 | 0 | } else |
782 | 0 | ret = (*a); |
783 | | |
784 | 0 | if (!ASN1_INTEGER_valid(ret)) { |
785 | 0 | i = ERR_R_ASN1_LENGTH_MISMATCH; |
786 | 0 | goto err; |
787 | 0 | } |
788 | | |
789 | 0 | p = *pp; |
790 | 0 | inf = ASN1_get_object(&p, &len, &tag, &xclass, length); |
791 | 0 | if (inf & 0x80) { |
792 | 0 | i = ASN1_R_BAD_OBJECT_HEADER; |
793 | 0 | goto err; |
794 | 0 | } |
795 | | |
796 | 0 | if (tag != V_ASN1_INTEGER) { |
797 | 0 | i = ASN1_R_EXPECTING_AN_INTEGER; |
798 | 0 | goto err; |
799 | 0 | } |
800 | | |
801 | | /* We must malloc stuff, even for 0 bytes otherwise it |
802 | | * signifies a missing NULL parameter. */ |
803 | 0 | if (len < 0 || len > INT_MAX) { |
804 | 0 | i = ERR_R_ASN1_LENGTH_MISMATCH; |
805 | 0 | goto err; |
806 | 0 | } |
807 | 0 | s = malloc(len + 1); |
808 | 0 | if (s == NULL) { |
809 | 0 | i = ERR_R_MALLOC_FAILURE; |
810 | 0 | goto err; |
811 | 0 | } |
812 | 0 | ret->type = V_ASN1_INTEGER; |
813 | 0 | if (len) { |
814 | 0 | if ((*p == 0) && (len != 1)) { |
815 | 0 | p++; |
816 | 0 | len--; |
817 | 0 | } |
818 | 0 | memcpy(s, p, len); |
819 | 0 | p += len; |
820 | 0 | } |
821 | |
|
822 | 0 | free(ret->data); |
823 | 0 | ret->data = s; |
824 | 0 | ret->length = (int)len; |
825 | 0 | if (a != NULL) |
826 | 0 | (*a) = ret; |
827 | 0 | *pp = p; |
828 | 0 | return (ret); |
829 | | |
830 | 0 | err: |
831 | 0 | ASN1error(i); |
832 | 0 | if (a == NULL || *a != ret) |
833 | 0 | ASN1_INTEGER_free(ret); |
834 | 0 | return (NULL); |
835 | 0 | } |