PolarSSL v1.3.9
asn1parse.c
Go to the documentation of this file.
1/*
2 * Generic ASN.1 parsing
3 *
4 * Copyright (C) 2006-2014, Brainspark B.V.
5 *
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#if !defined(POLARSSL_CONFIG_FILE)
27#include "polarssl/config.h"
28#else
29#include POLARSSL_CONFIG_FILE
30#endif
31
32#if defined(POLARSSL_ASN1_PARSE_C)
33
34#include "polarssl/asn1.h"
35
36#if defined(POLARSSL_BIGNUM_C)
37#include "polarssl/bignum.h"
38#endif
39
40#if defined(POLARSSL_PLATFORM_C)
41#include "polarssl/platform.h"
42#else
43#define polarssl_malloc malloc
44#define polarssl_free free
45#endif
46
47#include <string.h>
48#include <stdlib.h>
49
50/* Implementation that should never be optimized out by the compiler */
51static void polarssl_zeroize( void *v, size_t n ) {
52 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
53}
54
55/*
56 * ASN.1 DER decoding routines
57 */
58int asn1_get_len( unsigned char **p,
59 const unsigned char *end,
60 size_t *len )
61{
62 if( ( end - *p ) < 1 )
64
65 if( ( **p & 0x80 ) == 0 )
66 *len = *(*p)++;
67 else
68 {
69 switch( **p & 0x7F )
70 {
71 case 1:
72 if( ( end - *p ) < 2 )
74
75 *len = (*p)[1];
76 (*p) += 2;
77 break;
78
79 case 2:
80 if( ( end - *p ) < 3 )
82
83 *len = ( (*p)[1] << 8 ) | (*p)[2];
84 (*p) += 3;
85 break;
86
87 case 3:
88 if( ( end - *p ) < 4 )
90
91 *len = ( (*p)[1] << 16 ) | ( (*p)[2] << 8 ) | (*p)[3];
92 (*p) += 4;
93 break;
94
95 case 4:
96 if( ( end - *p ) < 5 )
98
99 *len = ( (*p)[1] << 24 ) | ( (*p)[2] << 16 ) | ( (*p)[3] << 8 ) |
100 (*p)[4];
101 (*p) += 5;
102 break;
103
104 default:
106 }
107 }
108
109 if( *len > (size_t) ( end - *p ) )
111
112 return( 0 );
113}
114
115int asn1_get_tag( unsigned char **p,
116 const unsigned char *end,
117 size_t *len, int tag )
118{
119 if( ( end - *p ) < 1 )
121
122 if( **p != tag )
124
125 (*p)++;
126
127 return( asn1_get_len( p, end, len ) );
128}
129
130int asn1_get_bool( unsigned char **p,
131 const unsigned char *end,
132 int *val )
133{
134 int ret;
135 size_t len;
136
137 if( ( ret = asn1_get_tag( p, end, &len, ASN1_BOOLEAN ) ) != 0 )
138 return( ret );
139
140 if( len != 1 )
142
143 *val = ( **p != 0 ) ? 1 : 0;
144 (*p)++;
145
146 return( 0 );
147}
148
149int asn1_get_int( unsigned char **p,
150 const unsigned char *end,
151 int *val )
152{
153 int ret;
154 size_t len;
155
156 if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
157 return( ret );
158
159 if( len > sizeof( int ) || ( **p & 0x80 ) != 0 )
161
162 *val = 0;
163
164 while( len-- > 0 )
165 {
166 *val = ( *val << 8 ) | **p;
167 (*p)++;
168 }
169
170 return( 0 );
171}
172
173#if defined(POLARSSL_BIGNUM_C)
174int asn1_get_mpi( unsigned char **p,
175 const unsigned char *end,
176 mpi *X )
177{
178 int ret;
179 size_t len;
180
181 if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
182 return( ret );
183
184 ret = mpi_read_binary( X, *p, len );
185
186 *p += len;
187
188 return( ret );
189}
190#endif /* POLARSSL_BIGNUM_C */
191
192int asn1_get_bitstring( unsigned char **p, const unsigned char *end,
193 asn1_bitstring *bs)
194{
195 int ret;
196
197 /* Certificate type is a single byte bitstring */
198 if( ( ret = asn1_get_tag( p, end, &bs->len, ASN1_BIT_STRING ) ) != 0 )
199 return( ret );
200
201 /* Check length, subtract one for actual bit string length */
202 if( bs->len < 1 )
204 bs->len -= 1;
205
206 /* Get number of unused bits, ensure unused bits <= 7 */
207 bs->unused_bits = **p;
208 if( bs->unused_bits > 7 )
210 (*p)++;
211
212 /* Get actual bitstring */
213 bs->p = *p;
214 *p += bs->len;
215
216 if( *p != end )
218
219 return( 0 );
220}
221
222/*
223 * Get a bit string without unused bits
224 */
225int asn1_get_bitstring_null( unsigned char **p, const unsigned char *end,
226 size_t *len )
227{
228 int ret;
229
230 if( ( ret = asn1_get_tag( p, end, len, ASN1_BIT_STRING ) ) != 0 )
231 return( ret );
232
233 if( (*len)-- < 2 || *(*p)++ != 0 )
235
236 return( 0 );
237}
238
239
240
241/*
242 * Parses and splits an ASN.1 "SEQUENCE OF <tag>"
243 */
244int asn1_get_sequence_of( unsigned char **p,
245 const unsigned char *end,
246 asn1_sequence *cur,
247 int tag)
248{
249 int ret;
250 size_t len;
251 asn1_buf *buf;
252
253 /* Get main sequence tag */
254 if( ( ret = asn1_get_tag( p, end, &len,
256 return( ret );
257
258 if( *p + len != end )
260
261 while( *p < end )
262 {
263 buf = &(cur->buf);
264 buf->tag = **p;
265
266 if( ( ret = asn1_get_tag( p, end, &buf->len, tag ) ) != 0 )
267 return( ret );
268
269 buf->p = *p;
270 *p += buf->len;
271
272 /* Allocate and assign next pointer */
273 if( *p < end )
274 {
276 sizeof( asn1_sequence ) );
277
278 if( cur->next == NULL )
280
281 memset( cur->next, 0, sizeof( asn1_sequence ) );
282
283 cur = cur->next;
284 }
285 }
286
287 /* Set final sequence entry's next pointer to NULL */
288 cur->next = NULL;
289
290 if( *p != end )
292
293 return( 0 );
294}
295
296int asn1_get_alg( unsigned char **p,
297 const unsigned char *end,
298 asn1_buf *alg, asn1_buf *params )
299{
300 int ret;
301 size_t len;
302
303 if( ( ret = asn1_get_tag( p, end, &len,
305 return( ret );
306
307 if( ( end - *p ) < 1 )
309
310 alg->tag = **p;
311 end = *p + len;
312
313 if( ( ret = asn1_get_tag( p, end, &alg->len, ASN1_OID ) ) != 0 )
314 return( ret );
315
316 alg->p = *p;
317 *p += alg->len;
318
319 if( *p == end )
320 {
321 polarssl_zeroize( params, sizeof(asn1_buf) );
322 return( 0 );
323 }
324
325 params->tag = **p;
326 (*p)++;
327
328 if( ( ret = asn1_get_len( p, end, &params->len ) ) != 0 )
329 return( ret );
330
331 params->p = *p;
332 *p += params->len;
333
334 if( *p != end )
336
337 return( 0 );
338}
339
340int asn1_get_alg_null( unsigned char **p,
341 const unsigned char *end,
342 asn1_buf *alg )
343{
344 int ret;
345 asn1_buf params;
346
347 memset( &params, 0, sizeof(asn1_buf) );
348
349 if( ( ret = asn1_get_alg( p, end, alg, &params ) ) != 0 )
350 return( ret );
351
352 if( ( params.tag != ASN1_NULL && params.tag != 0 ) || params.len != 0 )
354
355 return( 0 );
356}
357
359{
360 if( cur == NULL )
361 return;
362
363 polarssl_free( cur->oid.p );
364 polarssl_free( cur->val.p );
365
366 polarssl_zeroize( cur, sizeof( asn1_named_data ) );
367}
368
370{
371 asn1_named_data *cur;
372
373 while( ( cur = *head ) != NULL )
374 {
375 *head = cur->next;
377 polarssl_free( cur );
378 }
379}
380
382 const char *oid, size_t len )
383{
384 while( list != NULL )
385 {
386 if( list->oid.len == len &&
387 memcmp( list->oid.p, oid, len ) == 0 )
388 {
389 break;
390 }
391
392 list = list->next;
393 }
394
395 return( list );
396}
397
398#endif /* POLARSSL_ASN1_PARSE_C */
Generic ASN.1 parsing.
Multi-precision integer library.
int mpi_read_binary(mpi *X, const unsigned char *buf, size_t buflen)
Import X from unsigned binary data, big endian.
Configuration options (set of defines)
#define POLARSSL_ERR_ASN1_OUT_OF_DATA
Out of data when parsing an ASN1 data structure.
Definition asn1.h:54
size_t len
ASN1 length, e.g.
Definition asn1.h:137
#define POLARSSL_ERR_ASN1_INVALID_LENGTH
Error when trying to determine the length or invalid length.
Definition asn1.h:56
int asn1_get_bool(unsigned char **p, const unsigned char *end, int *val)
Retrieve a boolean ASN.1 tag and its value.
asn1_buf buf
Buffer containing the given ASN.1 item.
Definition asn1.h:148
#define ASN1_INTEGER
Definition asn1.h:76
#define ASN1_BIT_STRING
Definition asn1.h:77
int tag
ASN1 type, e.g.
Definition asn1.h:126
#define POLARSSL_ERR_ASN1_UNEXPECTED_TAG
ASN1 tag was of an unexpected value.
Definition asn1.h:55
#define POLARSSL_ERR_ASN1_MALLOC_FAILED
Memory allocation failed.
Definition asn1.h:59
#define ASN1_NULL
Definition asn1.h:79
#define ASN1_OID
Definition asn1.h:80
size_t len
ASN1 length, e.g.
Definition asn1.h:127
int asn1_get_alg(unsigned char **p, const unsigned char *end, asn1_buf *alg, asn1_buf *params)
Retrieve an AlgorithmIdentifier ASN.1 sequence.
int asn1_get_bitstring_null(unsigned char **p, const unsigned char *end, size_t *len)
Retrieve a bitstring ASN.1 tag without unused bits and its value.
void asn1_free_named_data(asn1_named_data *entry)
Free a asn1_named_data entry.
struct _asn1_named_data * next
The next entry in the sequence.
Definition asn1.h:160
unsigned char unused_bits
Number of unused bits at the end of the string.
Definition asn1.h:138
unsigned char * p
ASN1 data, e.g.
Definition asn1.h:128
#define ASN1_BOOLEAN
Definition asn1.h:75
#define POLARSSL_ERR_ASN1_INVALID_DATA
Data is invalid.
Definition asn1.h:58
#define ASN1_CONSTRUCTED
Definition asn1.h:92
int asn1_get_bitstring(unsigned char **p, const unsigned char *end, asn1_bitstring *bs)
Retrieve a bitstring ASN.1 tag and its value.
int asn1_get_mpi(unsigned char **p, const unsigned char *end, mpi *X)
Retrieve a MPI value from an integer ASN.1 tag.
#define ASN1_SEQUENCE
Definition asn1.h:82
asn1_buf oid
The object identifier.
Definition asn1.h:158
int asn1_get_alg_null(unsigned char **p, const unsigned char *end, asn1_buf *alg)
Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no params.
unsigned char * p
Raw ASN1 data for the bit string.
Definition asn1.h:139
int asn1_get_int(unsigned char **p, const unsigned char *end, int *val)
Retrieve an integer ASN.1 tag and its value.
asn1_named_data * asn1_find_named_data(asn1_named_data *list, const char *oid, size_t len)
Find a specific named_data entry in a sequence or list based on the OID.
int asn1_get_len(unsigned char **p, const unsigned char *end, size_t *len)
Get the length of an ASN.1 element.
void asn1_free_named_data_list(asn1_named_data **head)
Free all entries in a asn1_named_data list Head will be set to NULL.
asn1_buf val
The named value.
Definition asn1.h:159
struct _asn1_sequence * next
The next entry in the sequence.
Definition asn1.h:149
int asn1_get_tag(unsigned char **p, const unsigned char *end, size_t *len, int tag)
Get the tag and length of the tag.
int asn1_get_sequence_of(unsigned char **p, const unsigned char *end, asn1_sequence *cur, int tag)
Parses and splits an ASN.1 "SEQUENCE OF <tag>" Updated the pointer to immediately behind the full seq...
#define POLARSSL_ERR_ASN1_LENGTH_MISMATCH
Actual length differs from expected length.
Definition asn1.h:57
PolarSSL Platform abstraction layer.
Container for ASN1 bit strings.
Definition asn1.h:136
Type-length-value structure that allows for ASN1 using DER.
Definition asn1.h:125
Container for a sequence or list of 'named' ASN.1 data items.
Definition asn1.h:157
Container for a sequence of ASN.1 items.
Definition asn1.h:147
MPI structure.
Definition bignum.h:183
#define polarssl_malloc
#define polarssl_free