• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &params->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(&params, 0, sizeof(mbedtls_asn1_buf));
434 
435     if ((ret = mbedtls_asn1_get_alg(p, end, alg, &params)) != 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