1 /*
2 * Generic ASN.1 parsing
3 *
4 * Copyright The Mbed TLS Contributors
5 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 */
7
8 #include "common.h"
9
10 #if defined(MBEDTLS_ASN1_PARSE_C)
11
12 #include "mbedtls/asn1.h"
13 #include "mbedtls/platform_util.h"
14 #include "mbedtls/error.h"
15
16 #include <string.h>
17
18 #if defined(MBEDTLS_BIGNUM_C)
19 #include "mbedtls/bignum.h"
20 #endif
21
22 #include "mbedtls/platform.h"
23
24 /*
25 * ASN.1 DER decoding routines
26 */
mbedtls_asn1_get_len(unsigned char ** p,const unsigned char * end,size_t * len)27 int mbedtls_asn1_get_len(unsigned char **p,
28 const unsigned char *end,
29 size_t *len)
30 {
31 if ((end - *p) < 1) {
32 return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
33 }
34
35 if ((**p & 0x80) == 0) {
36 *len = *(*p)++;
37 } else {
38 switch (**p & 0x7F) {
39 case 1:
40 if ((end - *p) < 2) {
41 return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
42 }
43
44 *len = (*p)[1];
45 (*p) += 2;
46 break;
47
48 case 2:
49 if ((end - *p) < 3) {
50 return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
51 }
52
53 *len = ((size_t) (*p)[1] << 8) | (*p)[2];
54 (*p) += 3;
55 break;
56
57 case 3:
58 if ((end - *p) < 4) {
59 return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
60 }
61
62 *len = ((size_t) (*p)[1] << 16) |
63 ((size_t) (*p)[2] << 8) | (*p)[3];
64 (*p) += 4;
65 break;
66
67 case 4:
68 if ((end - *p) < 5) {
69 return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
70 }
71
72 *len = ((size_t) (*p)[1] << 24) | ((size_t) (*p)[2] << 16) |
73 ((size_t) (*p)[3] << 8) | (*p)[4];
74 (*p) += 5;
75 break;
76
77 default:
78 return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
79 }
80 }
81
82 if (*len > (size_t) (end - *p)) {
83 return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
84 }
85
86 return 0;
87 }
88
mbedtls_asn1_get_tag(unsigned char ** p,const unsigned char * end,size_t * len,int tag)89 int mbedtls_asn1_get_tag(unsigned char **p,
90 const unsigned char *end,
91 size_t *len, int tag)
92 {
93 if ((end - *p) < 1) {
94 return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
95 }
96
97 if (**p != tag) {
98 return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;
99 }
100
101 (*p)++;
102
103 return mbedtls_asn1_get_len(p, end, len);
104 }
105
mbedtls_asn1_get_bool(unsigned char ** p,const unsigned char * end,int * val)106 int mbedtls_asn1_get_bool(unsigned char **p,
107 const unsigned char *end,
108 int *val)
109 {
110 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
111 size_t len;
112
113 if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_BOOLEAN)) != 0) {
114 return ret;
115 }
116
117 if (len != 1) {
118 return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
119 }
120
121 *val = (**p != 0) ? 1 : 0;
122 (*p)++;
123
124 return 0;
125 }
126
asn1_get_tagged_int(unsigned char ** p,const unsigned char * end,int tag,int * val)127 static int asn1_get_tagged_int(unsigned char **p,
128 const unsigned char *end,
129 int tag, int *val)
130 {
131 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
132 size_t len;
133
134 if ((ret = mbedtls_asn1_get_tag(p, end, &len, tag)) != 0) {
135 return ret;
136 }
137
138 /*
139 * len==0 is malformed (0 must be represented as 020100 for INTEGER,
140 * or 0A0100 for ENUMERATED tags
141 */
142 if (len == 0) {
143 return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
144 }
145 /* This is a cryptography library. Reject negative integers. */
146 if ((**p & 0x80) != 0) {
147 return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
148 }
149
150 /* Skip leading zeros. */
151 while (len > 0 && **p == 0) {
152 ++(*p);
153 --len;
154 }
155
156 /* Reject integers that don't fit in an int. This code assumes that
157 * the int type has no padding bit. */
158 if (len > sizeof(int)) {
159 return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
160 }
161 if (len == sizeof(int) && (**p & 0x80) != 0) {
162 return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
163 }
164
165 *val = 0;
166 while (len-- > 0) {
167 *val = (*val << 8) | **p;
168 (*p)++;
169 }
170
171 return 0;
172 }
173
mbedtls_asn1_get_int(unsigned char ** p,const unsigned char * end,int * val)174 int mbedtls_asn1_get_int(unsigned char **p,
175 const unsigned char *end,
176 int *val)
177 {
178 return asn1_get_tagged_int(p, end, MBEDTLS_ASN1_INTEGER, val);
179 }
180
mbedtls_asn1_get_enum(unsigned char ** p,const unsigned char * end,int * val)181 int mbedtls_asn1_get_enum(unsigned char **p,
182 const unsigned char *end,
183 int *val)
184 {
185 return asn1_get_tagged_int(p, end, MBEDTLS_ASN1_ENUMERATED, val);
186 }
187
188 #if defined(MBEDTLS_BIGNUM_C)
mbedtls_asn1_get_mpi(unsigned char ** p,const unsigned char * end,mbedtls_mpi * X)189 int mbedtls_asn1_get_mpi(unsigned char **p,
190 const unsigned char *end,
191 mbedtls_mpi *X)
192 {
193 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
194 size_t len;
195
196 if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
197 return ret;
198 }
199
200 ret = mbedtls_mpi_read_binary(X, *p, len);
201
202 *p += len;
203
204 return ret;
205 }
206 #endif /* MBEDTLS_BIGNUM_C */
207
mbedtls_asn1_get_bitstring(unsigned char ** p,const unsigned char * end,mbedtls_asn1_bitstring * bs)208 int mbedtls_asn1_get_bitstring(unsigned char **p, const unsigned char *end,
209 mbedtls_asn1_bitstring *bs)
210 {
211 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
212
213 /* Certificate type is a single byte bitstring */
214 if ((ret = mbedtls_asn1_get_tag(p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING)) != 0) {
215 return ret;
216 }
217
218 /* Check length, subtract one for actual bit string length */
219 if (bs->len < 1) {
220 return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
221 }
222 bs->len -= 1;
223
224 /* Get number of unused bits, ensure unused bits <= 7 */
225 bs->unused_bits = **p;
226 if (bs->unused_bits > 7) {
227 return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
228 }
229 (*p)++;
230
231 /* Get actual bitstring */
232 bs->p = *p;
233 *p += bs->len;
234
235 if (*p != end) {
236 return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
237 }
238
239 return 0;
240 }
241
242 /*
243 * Traverse an ASN.1 "SEQUENCE OF <tag>"
244 * and call a callback for each entry found.
245 */
mbedtls_asn1_traverse_sequence_of(unsigned char ** p,const unsigned char * end,unsigned char tag_must_mask,unsigned char tag_must_val,unsigned char tag_may_mask,unsigned char tag_may_val,int (* cb)(void * ctx,int tag,unsigned char * start,size_t len),void * ctx)246 int mbedtls_asn1_traverse_sequence_of(
247 unsigned char **p,
248 const unsigned char *end,
249 unsigned char tag_must_mask, unsigned char tag_must_val,
250 unsigned char tag_may_mask, unsigned char tag_may_val,
251 int (*cb)(void *ctx, int tag,
252 unsigned char *start, size_t len),
253 void *ctx)
254 {
255 int ret;
256 size_t len;
257
258 /* Get main sequence tag */
259 if ((ret = mbedtls_asn1_get_tag(p, end, &len,
260 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
261 return ret;
262 }
263
264 if (*p + len != end) {
265 return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
266 }
267
268 while (*p < end) {
269 unsigned char const tag = *(*p)++;
270
271 if ((tag & tag_must_mask) != tag_must_val) {
272 return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;
273 }
274
275 if ((ret = mbedtls_asn1_get_len(p, end, &len)) != 0) {
276 return ret;
277 }
278
279 if ((tag & tag_may_mask) == tag_may_val) {
280 if (cb != NULL) {
281 ret = cb(ctx, tag, *p, len);
282 if (ret != 0) {
283 return ret;
284 }
285 }
286 }
287
288 *p += len;
289 }
290
291 return 0;
292 }
293
294 /*
295 * Get a bit string without unused bits
296 */
mbedtls_asn1_get_bitstring_null(unsigned char ** p,const unsigned char * end,size_t * len)297 int mbedtls_asn1_get_bitstring_null(unsigned char **p, const unsigned char *end,
298 size_t *len)
299 {
300 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
301
302 if ((ret = mbedtls_asn1_get_tag(p, end, len, MBEDTLS_ASN1_BIT_STRING)) != 0) {
303 return ret;
304 }
305
306 if (*len == 0) {
307 return MBEDTLS_ERR_ASN1_INVALID_DATA;
308 }
309 --(*len);
310
311 if (**p != 0) {
312 return MBEDTLS_ERR_ASN1_INVALID_DATA;
313 }
314 ++(*p);
315
316 return 0;
317 }
318
mbedtls_asn1_sequence_free(mbedtls_asn1_sequence * seq)319 void mbedtls_asn1_sequence_free(mbedtls_asn1_sequence *seq)
320 {
321 while (seq != NULL) {
322 mbedtls_asn1_sequence *next = seq->next;
323 mbedtls_platform_zeroize(seq, sizeof(*seq));
324 mbedtls_free(seq);
325 seq = next;
326 }
327 }
328
329 typedef struct {
330 int tag;
331 mbedtls_asn1_sequence *cur;
332 } asn1_get_sequence_of_cb_ctx_t;
333
asn1_get_sequence_of_cb(void * ctx,int tag,unsigned char * start,size_t len)334 static int asn1_get_sequence_of_cb(void *ctx,
335 int tag,
336 unsigned char *start,
337 size_t len)
338 {
339 asn1_get_sequence_of_cb_ctx_t *cb_ctx =
340 (asn1_get_sequence_of_cb_ctx_t *) ctx;
341 mbedtls_asn1_sequence *cur =
342 cb_ctx->cur;
343
344 if (cur->buf.p != NULL) {
345 cur->next =
346 mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));
347
348 if (cur->next == NULL) {
349 return MBEDTLS_ERR_ASN1_ALLOC_FAILED;
350 }
351
352 cur = cur->next;
353 }
354
355 cur->buf.p = start;
356 cur->buf.len = len;
357 cur->buf.tag = tag;
358
359 cb_ctx->cur = cur;
360 return 0;
361 }
362
363 /*
364 * Parses and splits an ASN.1 "SEQUENCE OF <tag>"
365 */
mbedtls_asn1_get_sequence_of(unsigned char ** p,const unsigned char * end,mbedtls_asn1_sequence * cur,int tag)366 int mbedtls_asn1_get_sequence_of(unsigned char **p,
367 const unsigned char *end,
368 mbedtls_asn1_sequence *cur,
369 int tag)
370 {
371 asn1_get_sequence_of_cb_ctx_t cb_ctx = { tag, cur };
372 memset(cur, 0, sizeof(mbedtls_asn1_sequence));
373 return mbedtls_asn1_traverse_sequence_of(
374 p, end, 0xFF, tag, 0, 0,
375 asn1_get_sequence_of_cb, &cb_ctx);
376 }
377
mbedtls_asn1_get_alg(unsigned char ** p,const unsigned char * end,mbedtls_asn1_buf * alg,mbedtls_asn1_buf * params)378 int mbedtls_asn1_get_alg(unsigned char **p,
379 const unsigned char *end,
380 mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params)
381 {
382 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
383 size_t len;
384
385 if ((ret = mbedtls_asn1_get_tag(p, end, &len,
386 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
387 return ret;
388 }
389
390 if ((end - *p) < 1) {
391 return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
392 }
393
394 alg->tag = **p;
395 end = *p + len;
396
397 if ((ret = mbedtls_asn1_get_tag(p, end, &alg->len, MBEDTLS_ASN1_OID)) != 0) {
398 return ret;
399 }
400
401 alg->p = *p;
402 *p += alg->len;
403
404 if (*p == end) {
405 mbedtls_platform_zeroize(params, sizeof(mbedtls_asn1_buf));
406 return 0;
407 }
408
409 params->tag = **p;
410 (*p)++;
411
412 if ((ret = mbedtls_asn1_get_len(p, end, ¶ms->len)) != 0) {
413 return ret;
414 }
415
416 params->p = *p;
417 *p += params->len;
418
419 if (*p != end) {
420 return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
421 }
422
423 return 0;
424 }
425
mbedtls_asn1_get_alg_null(unsigned char ** p,const unsigned char * end,mbedtls_asn1_buf * alg)426 int mbedtls_asn1_get_alg_null(unsigned char **p,
427 const unsigned char *end,
428 mbedtls_asn1_buf *alg)
429 {
430 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
431 mbedtls_asn1_buf params;
432
433 memset(¶ms, 0, sizeof(mbedtls_asn1_buf));
434
435 if ((ret = mbedtls_asn1_get_alg(p, end, alg, ¶ms)) != 0) {
436 return ret;
437 }
438
439 if ((params.tag != MBEDTLS_ASN1_NULL && params.tag != 0) || params.len != 0) {
440 return MBEDTLS_ERR_ASN1_INVALID_DATA;
441 }
442
443 return 0;
444 }
445
mbedtls_asn1_free_named_data(mbedtls_asn1_named_data * cur)446 void mbedtls_asn1_free_named_data(mbedtls_asn1_named_data *cur)
447 {
448 if (cur == NULL) {
449 return;
450 }
451
452 mbedtls_free(cur->oid.p);
453 mbedtls_free(cur->val.p);
454
455 mbedtls_platform_zeroize(cur, sizeof(mbedtls_asn1_named_data));
456 }
457
mbedtls_asn1_free_named_data_list(mbedtls_asn1_named_data ** head)458 void mbedtls_asn1_free_named_data_list(mbedtls_asn1_named_data **head)
459 {
460 mbedtls_asn1_named_data *cur;
461
462 while ((cur = *head) != NULL) {
463 *head = cur->next;
464 mbedtls_asn1_free_named_data(cur);
465 mbedtls_free(cur);
466 }
467 }
468
mbedtls_asn1_find_named_data(mbedtls_asn1_named_data * list,const char * oid,size_t len)469 mbedtls_asn1_named_data *mbedtls_asn1_find_named_data(mbedtls_asn1_named_data *list,
470 const char *oid, size_t len)
471 {
472 while (list != NULL) {
473 if (list->oid.len == len &&
474 memcmp(list->oid.p, oid, len) == 0) {
475 break;
476 }
477
478 list = list->next;
479 }
480
481 return list;
482 }
483
484 #endif /* MBEDTLS_ASN1_PARSE_C */
485