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