blob: d0a22343e3836b95a3b6da9d8ebef9d2c820ce6e [file] [log] [blame]
Paul Bakkerefc30292011-11-10 14:43:23 +00001/*
2 * Generic ASN.1 parsing
3 *
Paul Bakkerf8d018a2013-06-29 12:16:17 +02004 * Copyright (C) 2006-2013, Brainspark B.V.
Paul Bakkerefc30292011-11-10 14:43:23 +00005 *
6 * This file is part of PolarSSL (http://www.polarssl.org)
7 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
8 *
9 * All rights reserved.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 */
25
26#include "polarssl/config.h"
27
28#if defined(POLARSSL_ASN1_PARSE_C)
29
30#include "polarssl/asn1.h"
31
32#if defined(POLARSSL_BIGNUM_C)
33#include "polarssl/bignum.h"
34#endif
35
Paul Bakker6e339b52013-07-03 13:37:05 +020036#if defined(POLARSSL_MEMORY_C)
37#include "polarssl/memory.h"
38#else
39#define polarssl_malloc malloc
40#define polarssl_free free
41#endif
42
Paul Bakkerefc30292011-11-10 14:43:23 +000043#include <string.h>
44#include <stdlib.h>
45#include <time.h>
46
47/*
48 * ASN.1 DER decoding routines
49 */
50int asn1_get_len( unsigned char **p,
51 const unsigned char *end,
52 size_t *len )
53{
54 if( ( end - *p ) < 1 )
55 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
56
57 if( ( **p & 0x80 ) == 0 )
58 *len = *(*p)++;
59 else
60 {
61 switch( **p & 0x7F )
62 {
63 case 1:
64 if( ( end - *p ) < 2 )
65 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
66
67 *len = (*p)[1];
68 (*p) += 2;
69 break;
70
71 case 2:
72 if( ( end - *p ) < 3 )
73 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
74
75 *len = ( (*p)[1] << 8 ) | (*p)[2];
76 (*p) += 3;
77 break;
78
79 case 3:
80 if( ( end - *p ) < 4 )
81 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
82
83 *len = ( (*p)[1] << 16 ) | ( (*p)[2] << 8 ) | (*p)[3];
84 (*p) += 4;
85 break;
86
87 case 4:
88 if( ( end - *p ) < 5 )
89 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
90
91 *len = ( (*p)[1] << 24 ) | ( (*p)[2] << 16 ) | ( (*p)[3] << 8 ) | (*p)[4];
92 (*p) += 5;
93 break;
94
95 default:
96 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
97 }
98 }
99
100 if( *len > (size_t) ( end - *p ) )
101 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
102
103 return( 0 );
104}
105
106int asn1_get_tag( unsigned char **p,
107 const unsigned char *end,
108 size_t *len, int tag )
109{
110 if( ( end - *p ) < 1 )
111 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
112
113 if( **p != tag )
114 return( POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
115
116 (*p)++;
117
118 return( asn1_get_len( p, end, len ) );
119}
120
121int asn1_get_bool( unsigned char **p,
122 const unsigned char *end,
123 int *val )
124{
125 int ret;
126 size_t len;
127
128 if( ( ret = asn1_get_tag( p, end, &len, ASN1_BOOLEAN ) ) != 0 )
129 return( ret );
130
131 if( len != 1 )
132 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
133
134 *val = ( **p != 0 ) ? 1 : 0;
135 (*p)++;
136
137 return( 0 );
138}
139
140int asn1_get_int( unsigned char **p,
141 const unsigned char *end,
142 int *val )
143{
144 int ret;
145 size_t len;
146
147 if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
148 return( ret );
149
150 if( len > sizeof( int ) || ( **p & 0x80 ) != 0 )
151 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
152
153 *val = 0;
154
155 while( len-- > 0 )
156 {
157 *val = ( *val << 8 ) | **p;
158 (*p)++;
159 }
160
161 return( 0 );
162}
163
164#if defined(POLARSSL_BIGNUM_C)
165int asn1_get_mpi( unsigned char **p,
166 const unsigned char *end,
167 mpi *X )
168{
169 int ret;
170 size_t len;
171
172 if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
173 return( ret );
174
175 ret = mpi_read_binary( X, *p, len );
176
177 *p += len;
178
179 return( ret );
180}
181#endif /* POLARSSL_BIGNUM_C */
182
183int asn1_get_bitstring( unsigned char **p, const unsigned char *end,
184 asn1_bitstring *bs)
185{
186 int ret;
187
188 /* Certificate type is a single byte bitstring */
189 if( ( ret = asn1_get_tag( p, end, &bs->len, ASN1_BIT_STRING ) ) != 0 )
190 return( ret );
191
192 /* Check length, subtract one for actual bit string length */
193 if ( bs->len < 1 )
194 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
195 bs->len -= 1;
196
197 /* Get number of unused bits, ensure unused bits <= 7 */
198 bs->unused_bits = **p;
199 if( bs->unused_bits > 7 )
200 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
201 (*p)++;
202
203 /* Get actual bitstring */
204 bs->p = *p;
205 *p += bs->len;
206
207 if( *p != end )
208 return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
209
210 return 0;
211}
212
213
214/*
215 * Parses and splits an ASN.1 "SEQUENCE OF <tag>"
216 */
217int asn1_get_sequence_of( unsigned char **p,
218 const unsigned char *end,
219 asn1_sequence *cur,
220 int tag)
221{
222 int ret;
223 size_t len;
224 asn1_buf *buf;
225
226 /* Get main sequence tag */
227 if( ( ret = asn1_get_tag( p, end, &len,
228 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
229 return( ret );
230
231 if( *p + len != end )
232 return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
233
234 while( *p < end )
235 {
236 buf = &(cur->buf);
237 buf->tag = **p;
238
239 if( ( ret = asn1_get_tag( p, end, &buf->len, tag ) ) != 0 )
240 return( ret );
241
242 buf->p = *p;
243 *p += buf->len;
244
245 /* Allocate and assign next pointer */
246 if (*p < end)
247 {
Paul Bakker6e339b52013-07-03 13:37:05 +0200248 cur->next = (asn1_sequence *) polarssl_malloc(
Paul Bakkerefc30292011-11-10 14:43:23 +0000249 sizeof( asn1_sequence ) );
250
251 if( cur->next == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000252 return( POLARSSL_ERR_ASN1_MALLOC_FAILED );
Paul Bakkerefc30292011-11-10 14:43:23 +0000253
254 cur = cur->next;
255 }
256 }
257
258 /* Set final sequence entry's next pointer to NULL */
259 cur->next = NULL;
260
261 if( *p != end )
262 return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
263
264 return( 0 );
265}
266
Paul Bakkerf8d018a2013-06-29 12:16:17 +0200267int asn1_get_alg( unsigned char **p,
268 const unsigned char *end,
269 asn1_buf *alg, asn1_buf *params )
270{
271 int ret;
272 size_t len;
273
274 if( ( ret = asn1_get_tag( p, end, &len,
275 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
276 return( ret );
277
278 end = *p + len;
279 alg->tag = **p;
280
281 if( ( ret = asn1_get_tag( p, end, &alg->len, ASN1_OID ) ) != 0 )
282 return( ret );
283
284 alg->p = *p;
285 *p += alg->len;
286
287 if( *p == end )
288 {
289 memset( params, 0, sizeof(asn1_buf) );
290 return( 0 );
291 }
292
293 params->tag = **p;
294 (*p)++;
295
296 if( ( ret = asn1_get_len( p, end, &params->len ) ) != 0 )
297 return( ret );
298
299 params->p = *p;
300 *p += params->len;
301
302 if( *p != end )
303 return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
304
305 return( 0 );
306}
307
308int asn1_get_alg_null( unsigned char **p,
309 const unsigned char *end,
310 asn1_buf *alg )
311{
312 int ret;
313 asn1_buf params;
314
315 memset( &params, 0, sizeof(asn1_buf) );
316
317 if( ( ret = asn1_get_alg( p, end, alg, &params ) ) != 0 )
318 return( ret );
319
320 if( ( params.tag != ASN1_NULL && params.tag != 0 ) || params.len != 0 )
321 return( POLARSSL_ERR_ASN1_INVALID_DATA );
322
323 return( 0 );
324}
325
Paul Bakkerefc30292011-11-10 14:43:23 +0000326#endif