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