xref: /reactos/dll/3rdparty/mbedtls/asn1parse.c (revision b5218987)
1 /*
2  *  Generic ASN.1 parsing
3  *
4  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6  *
7  *  This file is provided under the Apache License 2.0, or the
8  *  GNU General Public License v2.0 or later.
9  *
10  *  **********
11  *  Apache License 2.0:
12  *
13  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
14  *  not use this file except in compliance with the License.
15  *  You may obtain a copy of the License at
16  *
17  *  http://www.apache.org/licenses/LICENSE-2.0
18  *
19  *  Unless required by applicable law or agreed to in writing, software
20  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22  *  See the License for the specific language governing permissions and
23  *  limitations under the License.
24  *
25  *  **********
26  *
27  *  **********
28  *  GNU General Public License v2.0 or later:
29  *
30  *  This program is free software; you can redistribute it and/or modify
31  *  it under the terms of the GNU General Public License as published by
32  *  the Free Software Foundation; either version 2 of the License, or
33  *  (at your option) any later version.
34  *
35  *  This program is distributed in the hope that it will be useful,
36  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
37  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
38  *  GNU General Public License for more details.
39  *
40  *  You should have received a copy of the GNU General Public License along
41  *  with this program; if not, write to the Free Software Foundation, Inc.,
42  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43  *
44  *  **********
45  *
46  *  This file is part of mbed TLS (https://tls.mbed.org)
47  */
48 
49 #if !defined(MBEDTLS_CONFIG_FILE)
50 #include "mbedtls/config.h"
51 #else
52 #include MBEDTLS_CONFIG_FILE
53 #endif
54 
55 #if defined(MBEDTLS_ASN1_PARSE_C)
56 
57 #include "mbedtls/asn1.h"
58 
59 #include <string.h>
60 
61 #if defined(MBEDTLS_BIGNUM_C)
62 #include "mbedtls/bignum.h"
63 #endif
64 
65 #if defined(MBEDTLS_PLATFORM_C)
66 #include "mbedtls/platform.h"
67 #else
68 #include <stdlib.h>
69 #define mbedtls_calloc    calloc
70 #define mbedtls_free       free
71 #endif
72 
73 /* Implementation that should never be optimized out by the compiler */
74 static void mbedtls_zeroize( void *v, size_t n ) {
75     volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
76 }
77 
78 /*
79  * ASN.1 DER decoding routines
80  */
81 int mbedtls_asn1_get_len( unsigned char **p,
82                   const unsigned char *end,
83                   size_t *len )
84 {
85     if( ( end - *p ) < 1 )
86         return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
87 
88     if( ( **p & 0x80 ) == 0 )
89         *len = *(*p)++;
90     else
91     {
92         switch( **p & 0x7F )
93         {
94         case 1:
95             if( ( end - *p ) < 2 )
96                 return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
97 
98             *len = (*p)[1];
99             (*p) += 2;
100             break;
101 
102         case 2:
103             if( ( end - *p ) < 3 )
104                 return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
105 
106             *len = ( (size_t)(*p)[1] << 8 ) | (*p)[2];
107             (*p) += 3;
108             break;
109 
110         case 3:
111             if( ( end - *p ) < 4 )
112                 return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
113 
114             *len = ( (size_t)(*p)[1] << 16 ) |
115                    ( (size_t)(*p)[2] << 8  ) | (*p)[3];
116             (*p) += 4;
117             break;
118 
119         case 4:
120             if( ( end - *p ) < 5 )
121                 return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
122 
123             *len = ( (size_t)(*p)[1] << 24 ) | ( (size_t)(*p)[2] << 16 ) |
124                    ( (size_t)(*p)[3] << 8  ) |           (*p)[4];
125             (*p) += 5;
126             break;
127 
128         default:
129             return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
130         }
131     }
132 
133     if( *len > (size_t) ( end - *p ) )
134         return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
135 
136     return( 0 );
137 }
138 
139 int mbedtls_asn1_get_tag( unsigned char **p,
140                   const unsigned char *end,
141                   size_t *len, int tag )
142 {
143     if( ( end - *p ) < 1 )
144         return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
145 
146     if( **p != tag )
147         return( MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
148 
149     (*p)++;
150 
151     return( mbedtls_asn1_get_len( p, end, len ) );
152 }
153 
154 int mbedtls_asn1_get_bool( unsigned char **p,
155                    const unsigned char *end,
156                    int *val )
157 {
158     int ret;
159     size_t len;
160 
161     if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_BOOLEAN ) ) != 0 )
162         return( ret );
163 
164     if( len != 1 )
165         return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
166 
167     *val = ( **p != 0 ) ? 1 : 0;
168     (*p)++;
169 
170     return( 0 );
171 }
172 
173 int mbedtls_asn1_get_int( unsigned char **p,
174                   const unsigned char *end,
175                   int *val )
176 {
177     int ret;
178     size_t len;
179 
180     if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 )
181         return( ret );
182 
183     if( len == 0 || len > sizeof( int ) || ( **p & 0x80 ) != 0 )
184         return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
185 
186     *val = 0;
187 
188     while( len-- > 0 )
189     {
190         *val = ( *val << 8 ) | **p;
191         (*p)++;
192     }
193 
194     return( 0 );
195 }
196 
197 #if defined(MBEDTLS_BIGNUM_C)
198 int mbedtls_asn1_get_mpi( unsigned char **p,
199                   const unsigned char *end,
200                   mbedtls_mpi *X )
201 {
202     int ret;
203     size_t len;
204 
205     if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 )
206         return( ret );
207 
208     ret = mbedtls_mpi_read_binary( X, *p, len );
209 
210     *p += len;
211 
212     return( ret );
213 }
214 #endif /* MBEDTLS_BIGNUM_C */
215 
216 int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end,
217                         mbedtls_asn1_bitstring *bs)
218 {
219     int ret;
220 
221     /* Certificate type is a single byte bitstring */
222     if( ( ret = mbedtls_asn1_get_tag( p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 )
223         return( ret );
224 
225     /* Check length, subtract one for actual bit string length */
226     if( bs->len < 1 )
227         return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
228     bs->len -= 1;
229 
230     /* Get number of unused bits, ensure unused bits <= 7 */
231     bs->unused_bits = **p;
232     if( bs->unused_bits > 7 )
233         return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
234     (*p)++;
235 
236     /* Get actual bitstring */
237     bs->p = *p;
238     *p += bs->len;
239 
240     if( *p != end )
241         return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
242 
243     return( 0 );
244 }
245 
246 /*
247  * Get a bit string without unused bits
248  */
249 int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end,
250                              size_t *len )
251 {
252     int ret;
253 
254     if( ( ret = mbedtls_asn1_get_tag( p, end, len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 )
255         return( ret );
256 
257     if( (*len)-- < 2 || *(*p)++ != 0 )
258         return( MBEDTLS_ERR_ASN1_INVALID_DATA );
259 
260     return( 0 );
261 }
262 
263 
264 
265 /*
266  *  Parses and splits an ASN.1 "SEQUENCE OF <tag>"
267  */
268 int mbedtls_asn1_get_sequence_of( unsigned char **p,
269                           const unsigned char *end,
270                           mbedtls_asn1_sequence *cur,
271                           int tag)
272 {
273     int ret;
274     size_t len;
275     mbedtls_asn1_buf *buf;
276 
277     /* Get main sequence tag */
278     if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
279             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
280         return( ret );
281 
282     if( *p + len != end )
283         return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
284 
285     while( *p < end )
286     {
287         buf = &(cur->buf);
288         buf->tag = **p;
289 
290         if( ( ret = mbedtls_asn1_get_tag( p, end, &buf->len, tag ) ) != 0 )
291             return( ret );
292 
293         buf->p = *p;
294         *p += buf->len;
295 
296         /* Allocate and assign next pointer */
297         if( *p < end )
298         {
299             cur->next = (mbedtls_asn1_sequence*)mbedtls_calloc( 1,
300                                             sizeof( mbedtls_asn1_sequence ) );
301 
302             if( cur->next == NULL )
303                 return( MBEDTLS_ERR_ASN1_ALLOC_FAILED );
304 
305             cur = cur->next;
306         }
307     }
308 
309     /* Set final sequence entry's next pointer to NULL */
310     cur->next = NULL;
311 
312     if( *p != end )
313         return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
314 
315     return( 0 );
316 }
317 
318 int mbedtls_asn1_get_alg( unsigned char **p,
319                   const unsigned char *end,
320                   mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params )
321 {
322     int ret;
323     size_t len;
324 
325     if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
326             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
327         return( ret );
328 
329     if( ( end - *p ) < 1 )
330         return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
331 
332     alg->tag = **p;
333     end = *p + len;
334 
335     if( ( ret = mbedtls_asn1_get_tag( p, end, &alg->len, MBEDTLS_ASN1_OID ) ) != 0 )
336         return( ret );
337 
338     alg->p = *p;
339     *p += alg->len;
340 
341     if( *p == end )
342     {
343         mbedtls_zeroize( params, sizeof(mbedtls_asn1_buf) );
344         return( 0 );
345     }
346 
347     params->tag = **p;
348     (*p)++;
349 
350     if( ( ret = mbedtls_asn1_get_len( p, end, &params->len ) ) != 0 )
351         return( ret );
352 
353     params->p = *p;
354     *p += params->len;
355 
356     if( *p != end )
357         return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
358 
359     return( 0 );
360 }
361 
362 int mbedtls_asn1_get_alg_null( unsigned char **p,
363                        const unsigned char *end,
364                        mbedtls_asn1_buf *alg )
365 {
366     int ret;
367     mbedtls_asn1_buf params;
368 
369     memset( &params, 0, sizeof(mbedtls_asn1_buf) );
370 
371     if( ( ret = mbedtls_asn1_get_alg( p, end, alg, &params ) ) != 0 )
372         return( ret );
373 
374     if( ( params.tag != MBEDTLS_ASN1_NULL && params.tag != 0 ) || params.len != 0 )
375         return( MBEDTLS_ERR_ASN1_INVALID_DATA );
376 
377     return( 0 );
378 }
379 
380 void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *cur )
381 {
382     if( cur == NULL )
383         return;
384 
385     mbedtls_free( cur->oid.p );
386     mbedtls_free( cur->val.p );
387 
388     mbedtls_zeroize( cur, sizeof( mbedtls_asn1_named_data ) );
389 }
390 
391 void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head )
392 {
393     mbedtls_asn1_named_data *cur;
394 
395     while( ( cur = *head ) != NULL )
396     {
397         *head = cur->next;
398         mbedtls_asn1_free_named_data( cur );
399         mbedtls_free( cur );
400     }
401 }
402 
403 mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( mbedtls_asn1_named_data *list,
404                                        const char *oid, size_t len )
405 {
406     while( list != NULL )
407     {
408         if( list->oid.len == len &&
409             memcmp( list->oid.p, oid, len ) == 0 )
410         {
411             break;
412         }
413 
414         list = list->next;
415     }
416 
417     return( list );
418 }
419 
420 #endif /* MBEDTLS_ASN1_PARSE_C */
421