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, &params->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(&params, 0, sizeof(mbedtls_asn1_buf));
407 
408     if ((ret = mbedtls_asn1_get_alg(p, end, alg, &params)) != 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