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  cur = cur->next;
248  }
249  }
250 
251  /* Set final sequence entry's next pointer to NULL */
252  cur->next = NULL;
253 
254  if( *p != end )
256 
257  return( 0 );
258 }
259 
260 #endif