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