blob: 5b86aa60e23af3a9e5cfb534926a8ded9c6c7361 [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>
Paul Bakkerefc30292011-11-10 14:43:23 +000045
46/*
47 * ASN.1 DER decoding routines
48 */
49int asn1_get_len( unsigned char **p,
50 const unsigned char *end,
51 size_t *len )
52{
53 if( ( end - *p ) < 1 )
54 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
55
56 if( ( **p & 0x80 ) == 0 )
57 *len = *(*p)++;
58 else
59 {
60 switch( **p & 0x7F )
61 {
62 case 1:
63 if( ( end - *p ) < 2 )
64 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
65
66 *len = (*p)[1];
67 (*p) += 2;
68 break;
69
70 case 2:
71 if( ( end - *p ) < 3 )
72 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
73
74 *len = ( (*p)[1] << 8 ) | (*p)[2];
75 (*p) += 3;
76 break;
77
78 case 3:
79 if( ( end - *p ) < 4 )
80 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
81
82 *len = ( (*p)[1] << 16 ) | ( (*p)[2] << 8 ) | (*p)[3];
83 (*p) += 4;
84 break;
85
86 case 4:
87 if( ( end - *p ) < 5 )
88 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
89
90 *len = ( (*p)[1] << 24 ) | ( (*p)[2] << 16 ) | ( (*p)[3] << 8 ) | (*p)[4];
91 (*p) += 5;
92 break;
93
94 default:
95 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
96 }
97 }
98
99 if( *len > (size_t) ( end - *p ) )
100 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
101
102 return( 0 );
103}
104
105int asn1_get_tag( unsigned char **p,
106 const unsigned char *end,
107 size_t *len, int tag )
108{
109 if( ( end - *p ) < 1 )
110 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
111
112 if( **p != tag )
113 return( POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
114
115 (*p)++;
116
117 return( asn1_get_len( p, end, len ) );
118}
119
120int asn1_get_bool( unsigned char **p,
121 const unsigned char *end,
122 int *val )
123{
124 int ret;
125 size_t len;
126
127 if( ( ret = asn1_get_tag( p, end, &len, ASN1_BOOLEAN ) ) != 0 )
128 return( ret );
129
130 if( len != 1 )
131 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
132
133 *val = ( **p != 0 ) ? 1 : 0;
134 (*p)++;
135
136 return( 0 );
137}
138
139int asn1_get_int( unsigned char **p,
140 const unsigned char *end,
141 int *val )
142{
143 int ret;
144 size_t len;
145
146 if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
147 return( ret );
148
149 if( len > sizeof( int ) || ( **p & 0x80 ) != 0 )
150 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
151
152 *val = 0;
153
154 while( len-- > 0 )
155 {
156 *val = ( *val << 8 ) | **p;
157 (*p)++;
158 }
159
160 return( 0 );
161}
162
163#if defined(POLARSSL_BIGNUM_C)
164int asn1_get_mpi( unsigned char **p,
165 const unsigned char *end,
166 mpi *X )
167{
168 int ret;
169 size_t len;
170
171 if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
172 return( ret );
173
174 ret = mpi_read_binary( X, *p, len );
175
176 *p += len;
177
178 return( ret );
179}
180#endif /* POLARSSL_BIGNUM_C */
181
182int asn1_get_bitstring( unsigned char **p, const unsigned char *end,
183 asn1_bitstring *bs)
184{
185 int ret;
186
187 /* Certificate type is a single byte bitstring */
188 if( ( ret = asn1_get_tag( p, end, &bs->len, ASN1_BIT_STRING ) ) != 0 )
189 return( ret );
190
191 /* Check length, subtract one for actual bit string length */
192 if ( bs->len < 1 )
193 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
194 bs->len -= 1;
195
196 /* Get number of unused bits, ensure unused bits <= 7 */
197 bs->unused_bits = **p;
198 if( bs->unused_bits > 7 )
199 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
200 (*p)++;
201
202 /* Get actual bitstring */
203 bs->p = *p;
204 *p += bs->len;
205
206 if( *p != end )
207 return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
208
209 return 0;
210}
211
212
213/*
214 * Parses and splits an ASN.1 "SEQUENCE OF <tag>"
215 */
216int asn1_get_sequence_of( unsigned char **p,
217 const unsigned char *end,
218 asn1_sequence *cur,
219 int tag)
220{
221 int ret;
222 size_t len;
223 asn1_buf *buf;
224
225 /* Get main sequence tag */
226 if( ( ret = asn1_get_tag( p, end, &len,
227 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
228 return( ret );
229
230 if( *p + len != end )
231 return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
232
233 while( *p < end )
234 {
235 buf = &(cur->buf);
236 buf->tag = **p;
237
238 if( ( ret = asn1_get_tag( p, end, &buf->len, tag ) ) != 0 )
239 return( ret );
240
241 buf->p = *p;
242 *p += buf->len;
243
244 /* Allocate and assign next pointer */
245 if (*p < end)
246 {
Paul Bakker6e339b52013-07-03 13:37:05 +0200247 cur->next = (asn1_sequence *) polarssl_malloc(
Paul Bakkerefc30292011-11-10 14:43:23 +0000248 sizeof( asn1_sequence ) );
249
250 if( cur->next == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000251 return( POLARSSL_ERR_ASN1_MALLOC_FAILED );
Paul Bakkerefc30292011-11-10 14:43:23 +0000252
253 cur = cur->next;
254 }
255 }
256
257 /* Set final sequence entry's next pointer to NULL */
258 cur->next = NULL;
259
260 if( *p != end )
261 return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
262
263 return( 0 );
264}
265
Paul Bakkerf8d018a2013-06-29 12:16:17 +0200266int asn1_get_alg( unsigned char **p,
267 const unsigned char *end,
268 asn1_buf *alg, asn1_buf *params )
269{
270 int ret;
271 size_t len;
272
273 if( ( ret = asn1_get_tag( p, end, &len,
274 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
275 return( ret );
276
277 end = *p + len;
278 alg->tag = **p;
279
280 if( ( ret = asn1_get_tag( p, end, &alg->len, ASN1_OID ) ) != 0 )
281 return( ret );
282
283 alg->p = *p;
284 *p += alg->len;
285
286 if( *p == end )
287 {
288 memset( params, 0, sizeof(asn1_buf) );
289 return( 0 );
290 }
291
292 params->tag = **p;
293 (*p)++;
294
295 if( ( ret = asn1_get_len( p, end, &params->len ) ) != 0 )
296 return( ret );
297
298 params->p = *p;
299 *p += params->len;
300
301 if( *p != end )
302 return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
303
304 return( 0 );
305}
306
307int asn1_get_alg_null( unsigned char **p,
308 const unsigned char *end,
309 asn1_buf *alg )
310{
311 int ret;
312 asn1_buf params;
313
314 memset( &params, 0, sizeof(asn1_buf) );
315
316 if( ( ret = asn1_get_alg( p, end, alg, &params ) ) != 0 )
317 return( ret );
318
319 if( ( params.tag != ASN1_NULL && params.tag != 0 ) || params.len != 0 )
320 return( POLARSSL_ERR_ASN1_INVALID_DATA );
321
322 return( 0 );
323}
324
Paul Bakkerefc30292011-11-10 14:43:23 +0000325#endif