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