PolarSSL v1.2.12
asn1parse.c
Go to the documentation of this file.
1 /*
2  * Generic ASN.1 parsing
3  *
4  * Copyright (C) 2006-2011, 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 #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 
36 #include <string.h>
37 #include <stdlib.h>
38 #include <time.h>
39 
40 /*
41  * ASN.1 DER decoding routines
42  */
43 int asn1_get_len( unsigned char **p,
44  const unsigned char *end,
45  size_t *len )
46 {
47  if( ( end - *p ) < 1 )
49 
50  if( ( **p & 0x80 ) == 0 )
51  *len = *(*p)++;
52  else
53  {
54  switch( **p & 0x7F )
55  {
56  case 1:
57  if( ( end - *p ) < 2 )
59 
60  *len = (*p)[1];
61  (*p) += 2;
62  break;
63 
64  case 2:
65  if( ( end - *p ) < 3 )
67 
68  *len = ( (*p)[1] << 8 ) | (*p)[2];
69  (*p) += 3;
70  break;
71 
72  case 3:
73  if( ( end - *p ) < 4 )
75 
76  *len = ( (*p)[1] << 16 ) | ( (*p)[2] << 8 ) | (*p)[3];
77  (*p) += 4;
78  break;
79 
80  case 4:
81  if( ( end - *p ) < 5 )
83 
84  *len = ( (*p)[1] << 24 ) | ( (*p)[2] << 16 ) | ( (*p)[3] << 8 ) | (*p)[4];
85  (*p) += 5;
86  break;
87 
88  default:
90  }
91  }
92 
93  if( *len > (size_t) ( end - *p ) )
95 
96  return( 0 );
97 }
98 
99 int asn1_get_tag( unsigned char **p,
100  const unsigned char *end,
101  size_t *len, int tag )
102 {
103  if( ( end - *p ) < 1 )
105 
106  if( **p != tag )
108 
109  (*p)++;
110 
111  return( asn1_get_len( p, end, len ) );
112 }
113 
114 int asn1_get_bool( unsigned char **p,
115  const unsigned char *end,
116  int *val )
117 {
118  int ret;
119  size_t len;
120 
121  if( ( ret = asn1_get_tag( p, end, &len, ASN1_BOOLEAN ) ) != 0 )
122  return( ret );
123 
124  if( len != 1 )
126 
127  *val = ( **p != 0 ) ? 1 : 0;
128  (*p)++;
129 
130  return( 0 );
131 }
132 
133 int asn1_get_int( unsigned char **p,
134  const unsigned char *end,
135  int *val )
136 {
137  int ret;
138  size_t len;
139 
140  if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
141  return( ret );
142 
143  if( len > sizeof( int ) || ( **p & 0x80 ) != 0 )
145 
146  *val = 0;
147 
148  while( len-- > 0 )
149  {
150  *val = ( *val << 8 ) | **p;
151  (*p)++;
152  }
153 
154  return( 0 );
155 }
156 
157 #if defined(POLARSSL_BIGNUM_C)
158 int asn1_get_mpi( unsigned char **p,
159  const unsigned char *end,
160  mpi *X )
161 {
162  int ret;
163  size_t len;
164 
165  if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
166  return( ret );
167 
168  ret = mpi_read_binary( X, *p, len );
169 
170  *p += len;
171 
172  return( ret );
173 }
174 #endif /* POLARSSL_BIGNUM_C */
175 
176 int asn1_get_bitstring( unsigned char **p, const unsigned char *end,
177  asn1_bitstring *bs)
178 {
179  int ret;
180 
181  /* Certificate type is a single byte bitstring */
182  if( ( ret = asn1_get_tag( p, end, &bs->len, ASN1_BIT_STRING ) ) != 0 )
183  return( ret );
184 
185  /* Check length, subtract one for actual bit string length */
186  if ( bs->len < 1 )
188  bs->len -= 1;
189 
190  /* Get number of unused bits, ensure unused bits <= 7 */
191  bs->unused_bits = **p;
192  if( bs->unused_bits > 7 )
194  (*p)++;
195 
196  /* Get actual bitstring */
197  bs->p = *p;
198  *p += bs->len;
199 
200  if( *p != end )
202 
203  return 0;
204 }
205 
206 
207 /*
208  * Parses and splits an ASN.1 "SEQUENCE OF <tag>"
209  */
210 int asn1_get_sequence_of( unsigned char **p,
211  const unsigned char *end,
212  asn1_sequence *cur,
213  int tag)
214 {
215  int ret;
216  size_t len;
217  asn1_buf *buf;
218 
219  /* Get main sequence tag */
220  if( ( ret = asn1_get_tag( p, end, &len,
221  ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
222  return( ret );
223 
224  if( *p + len != end )
226 
227  while( *p < end )
228  {
229  buf = &(cur->buf);
230  buf->tag = **p;
231 
232  if( ( ret = asn1_get_tag( p, end, &buf->len, tag ) ) != 0 )
233  return( ret );
234 
235  buf->p = *p;
236  *p += buf->len;
237 
238  /* Allocate and assign next pointer */
239  if (*p < end)
240  {
241  cur->next = (asn1_sequence *) malloc(
242  sizeof( asn1_sequence ) );
243 
244  if( cur->next == NULL )
246 
247  memset( cur->next, 0, sizeof( asn1_sequence ) );
248 
249  cur = cur->next;
250  }
251  }
252 
253  /* Set final sequence entry's next pointer to NULL */
254  cur->next = NULL;
255 
256  if( *p != end )
258 
259  return( 0 );
260 }
261 
262 #endif
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...
asn1_buf buf
Buffer containing the given ASN.1 item.
Definition: asn1.h:132
#define POLARSSL_ERR_ASN1_LENGTH_MISMATCH
Actual length differs from expected length.
Definition: asn1.h:53
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:121
#define ASN1_SEQUENCE
Definition: asn1.h:78
Configuration options (set of defines)
#define ASN1_CONSTRUCTED
Definition: asn1.h:88
unsigned char unused_bits
Number of unused bits at the end of the string.
Definition: asn1.h:122
MPI structure.
Definition: bignum.h:164
#define POLARSSL_ERR_ASN1_INVALID_LENGTH
Error when trying to determine the length or invalid length.
Definition: asn1.h:52
Container for ASN1 bit strings.
Definition: asn1.h:119
Multi-precision integer library.
Container for a sequence of ASN.1 items.
Definition: asn1.h:130
unsigned char * p
Raw ASN1 data for the bit string.
Definition: asn1.h:123
Generic ASN.1 parsing.
#define ASN1_INTEGER
Definition: asn1.h:72
unsigned char * p
ASN1 data, e.g.
Definition: asn1.h:112
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:110
#define POLARSSL_ERR_ASN1_OUT_OF_DATA
Out of data when parsing an ASN1 data structure.
Definition: asn1.h:50
#define ASN1_BIT_STRING
Definition: asn1.h:73
#define POLARSSL_ERR_ASN1_MALLOC_FAILED
Memory allocation failed.
Definition: asn1.h:55
int mpi_read_binary(mpi *X, const unsigned char *buf, size_t buflen)
Import X from unsigned binary data, big endian.
Type-length-value structure that allows for ASN1 using DER.
Definition: asn1.h:108
size_t len
ASN1 length, e.g.
Definition: asn1.h:111
#define ASN1_BOOLEAN
Definition: asn1.h:71
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.
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 POLARSSL_ERR_ASN1_UNEXPECTED_TAG
ASN1 tag was of an unexpected value.
Definition: asn1.h:51
struct _asn1_sequence * next
The next entry in the sequence.
Definition: asn1.h:133