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