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