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 */
51 static 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  */
58 int 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 
115 int 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 
130 int 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 
149 int 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)
174 int 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 
192 int 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  */
225 int 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  */
244 int 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,
255  ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
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 
296 int 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,
304  ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
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 
340 int 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;
376  asn1_free_named_data( cur );
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 */
#define ASN1_NULL
Definition: asn1.h:79
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 " Updated the pointer to immediately behind the full seq...
#define ASN1_OID
Definition: asn1.h:80
asn1_buf buf
Buffer containing the given ASN.1 item.
Definition: asn1.h:148
#define POLARSSL_ERR_ASN1_LENGTH_MISMATCH
Actual length differs from expected length.
Definition: asn1.h:57
int asn1_get_int(unsigned char **p, const unsigned char *end, int *val)
Retrieve an integer ASN.1 tag and its value.
size_t len
ASN1 length, e.g.
Definition: asn1.h:137
#define polarssl_free
Definition: platform.h:91
#define ASN1_SEQUENCE
Definition: asn1.h:82
Configuration options (set of defines)
#define POLARSSL_ERR_ASN1_INVALID_DATA
Data is invalid.
Definition: asn1.h:58
#define ASN1_CONSTRUCTED
Definition: asn1.h:92
unsigned char unused_bits
Number of unused bits at the end of the string.
Definition: asn1.h:138
MPI structure.
Definition: bignum.h:182
PolarSSL Platform abstraction layer.
#define POLARSSL_ERR_ASN1_INVALID_LENGTH
Error when trying to determine the length or invalid length.
Definition: asn1.h:56
Container for ASN1 bit strings.
Definition: asn1.h:135
Multi-precision integer library.
asn1_buf val
The named value.
Definition: asn1.h:159
Container for a sequence of ASN.1 items.
Definition: asn1.h:146
unsigned char * p
Raw ASN1 data for the bit string.
Definition: asn1.h:139
Generic ASN.1 parsing.
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.
int asn1_get_alg(unsigned char **p, const unsigned char *end, asn1_buf *alg, asn1_buf *params)
Retrieve an AlgorithmIdentifier ASN.1 sequence.
#define ASN1_INTEGER
Definition: asn1.h:76
unsigned char * p
ASN1 data, e.g.
Definition: asn1.h:128
int asn1_get_bool(unsigned char **p, const unsigned char *end, int *val)
Retrieve a boolean ASN.1 tag and its value.
int tag
ASN1 type, e.g.
Definition: asn1.h:126
#define POLARSSL_ERR_ASN1_OUT_OF_DATA
Out of data when parsing an ASN1 data structure.
Definition: asn1.h:54
void asn1_free_named_data(asn1_named_data *entry)
Free a asn1_named_data entry.
#define ASN1_BIT_STRING
Definition: asn1.h:77
#define POLARSSL_ERR_ASN1_MALLOC_FAILED
Memory allocation failed.
Definition: asn1.h:59
int mpi_read_binary(mpi *X, const unsigned char *buf, size_t buflen)
Import X from unsigned binary data, big endian.
Container for a sequence or list of 'named' ASN.1 data items.
Definition: asn1.h:156
Type-length-value structure that allows for ASN1 using DER.
Definition: asn1.h:124
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.
size_t len
ASN1 length, e.g.
Definition: asn1.h:127
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.
#define ASN1_BOOLEAN
Definition: asn1.h:75
int asn1_get_len(unsigned char **p, const unsigned char *end, size_t *len)
Get the length of an ASN.1 element.
int asn1_get_tag(unsigned char **p, const unsigned char *end, size_t *len, int tag)
Get the tag and length of the tag.
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_bitstring(unsigned char **p, const unsigned char *end, asn1_bitstring *bs)
Retrieve a bitstring ASN.1 tag and its value.
struct _asn1_named_data * next
The next entry in the sequence.
Definition: asn1.h:160
#define polarssl_malloc
Definition: platform.h:90
int asn1_get_mpi(unsigned char **p, const unsigned char *end, mpi *X)
Retrieve a MPI value from an integer ASN.1 tag.
#define POLARSSL_ERR_ASN1_UNEXPECTED_TAG
ASN1 tag was of an unexpected value.
Definition: asn1.h:55
struct _asn1_sequence * next
The next entry in the sequence.
Definition: asn1.h:149