blob: 74c4fd5e656e5bd0ffcaa1dc62e30a9611b6e8c9 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * X.509 certificate and private key decoding
3 *
Paul Bakker84f12b72010-07-18 10:13:04 +00004 * Copyright (C) 2006-2010, Brainspark B.V.
Paul Bakkerb96f1542010-07-18 20:36:00 +00005 *
6 * This file is part of PolarSSL (http://www.polarssl.org)
Paul Bakker84f12b72010-07-18 10:13:04 +00007 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
Paul Bakkerb96f1542010-07-18 20:36:00 +00008 *
Paul Bakker77b385e2009-07-28 17:23:11 +00009 * All rights reserved.
Paul Bakkere0ccd0a2009-01-04 16:27:10 +000010 *
Paul Bakker5121ce52009-01-03 21:22:43 +000011 * 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 * The ITU-T X.509 standard defines a certificat format for PKI.
27 *
28 * http://www.ietf.org/rfc/rfc2459.txt
29 * http://www.ietf.org/rfc/rfc3279.txt
30 *
31 * ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
32 *
33 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
34 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
35 */
36
Paul Bakker40e46942009-01-03 21:51:57 +000037#include "polarssl/config.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000038
Paul Bakker40e46942009-01-03 21:51:57 +000039#if defined(POLARSSL_X509_PARSE_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000040
Paul Bakker40e46942009-01-03 21:51:57 +000041#include "polarssl/x509.h"
Paul Bakker96743fc2011-02-12 14:30:57 +000042#include "polarssl/pem.h"
Paul Bakker40e46942009-01-03 21:51:57 +000043#include "polarssl/des.h"
44#include "polarssl/md2.h"
45#include "polarssl/md4.h"
46#include "polarssl/md5.h"
47#include "polarssl/sha1.h"
Paul Bakker026c03b2009-03-28 17:53:03 +000048#include "polarssl/sha2.h"
49#include "polarssl/sha4.h"
Paul Bakker1b57b062011-01-06 15:48:19 +000050#include "polarssl/dhm.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000051
52#include <string.h>
53#include <stdlib.h>
Paul Bakker5121ce52009-01-03 21:22:43 +000054#include <time.h>
55
Paul Bakker335db3f2011-04-25 15:28:35 +000056#if defined(POLARSSL_FS_IO)
57#include <stdio.h>
58#endif
59
Paul Bakker5121ce52009-01-03 21:22:43 +000060/*
61 * ASN.1 DER decoding routines
62 */
63static int asn1_get_len( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +000064 const unsigned char *end,
Paul Bakker23986e52011-04-24 08:57:21 +000065 size_t *len )
Paul Bakker5121ce52009-01-03 21:22:43 +000066{
67 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +000068 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000069
70 if( ( **p & 0x80 ) == 0 )
71 *len = *(*p)++;
72 else
73 {
74 switch( **p & 0x7F )
75 {
76 case 1:
77 if( ( end - *p ) < 2 )
Paul Bakker40e46942009-01-03 21:51:57 +000078 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000079
80 *len = (*p)[1];
81 (*p) += 2;
82 break;
83
84 case 2:
85 if( ( end - *p ) < 3 )
Paul Bakker40e46942009-01-03 21:51:57 +000086 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000087
88 *len = ( (*p)[1] << 8 ) | (*p)[2];
89 (*p) += 3;
90 break;
91
92 default:
Paul Bakker40e46942009-01-03 21:51:57 +000093 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
Paul Bakker5121ce52009-01-03 21:22:43 +000094 break;
95 }
96 }
97
Paul Bakker23986e52011-04-24 08:57:21 +000098 if( *len > (size_t) ( end - *p ) )
Paul Bakker40e46942009-01-03 21:51:57 +000099 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000100
101 return( 0 );
102}
103
104static int asn1_get_tag( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000105 const unsigned char *end,
Paul Bakker23986e52011-04-24 08:57:21 +0000106 size_t *len, int tag )
Paul Bakker5121ce52009-01-03 21:22:43 +0000107{
108 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000109 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000110
111 if( **p != tag )
Paul Bakker40e46942009-01-03 21:51:57 +0000112 return( POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000113
114 (*p)++;
115
116 return( asn1_get_len( p, end, len ) );
117}
118
119static int asn1_get_bool( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000120 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000121 int *val )
122{
Paul Bakker23986e52011-04-24 08:57:21 +0000123 int ret;
124 size_t len;
Paul Bakker5121ce52009-01-03 21:22:43 +0000125
126 if( ( ret = asn1_get_tag( p, end, &len, ASN1_BOOLEAN ) ) != 0 )
127 return( ret );
128
129 if( len != 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000130 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000131
132 *val = ( **p != 0 ) ? 1 : 0;
133 (*p)++;
134
135 return( 0 );
136}
137
138static int asn1_get_int( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000139 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000140 int *val )
141{
Paul Bakker23986e52011-04-24 08:57:21 +0000142 int ret;
143 size_t len;
Paul Bakker5121ce52009-01-03 21:22:43 +0000144
145 if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
146 return( ret );
147
Paul Bakker27fdf462011-06-09 13:55:13 +0000148 if( len > sizeof( int ) || ( **p & 0x80 ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000149 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000150
151 *val = 0;
152
153 while( len-- > 0 )
154 {
155 *val = ( *val << 8 ) | **p;
156 (*p)++;
157 }
158
159 return( 0 );
160}
161
162static int asn1_get_mpi( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000163 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000164 mpi *X )
165{
Paul Bakker23986e52011-04-24 08:57:21 +0000166 int ret;
167 size_t len;
Paul Bakker5121ce52009-01-03 21:22:43 +0000168
169 if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
170 return( ret );
171
172 ret = mpi_read_binary( X, *p, len );
173
174 *p += len;
175
176 return( ret );
177}
178
Paul Bakker74111d32011-01-15 16:57:55 +0000179static int asn1_get_bitstring( unsigned char **p, const unsigned char *end,
180 x509_bitstring *bs)
181{
182 int ret;
183
184 /* Certificate type is a single byte bitstring */
185 if( ( ret = asn1_get_tag( p, end, &bs->len, ASN1_BIT_STRING ) ) != 0 )
186 return( ret );
187
188 /* Check length, subtract one for actual bit string length */
189 if ( bs->len < 1 )
190 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
191 bs->len -= 1;
192
193 /* Get number of unused bits, ensure unused bits <= 7 */
194 bs->unused_bits = **p;
195 if( bs->unused_bits > 7 )
196 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
197 (*p)++;
198
199 /* Get actual bitstring */
200 bs->p = *p;
201 *p += bs->len;
202
203 if( *p != end )
204 return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
205
206 return 0;
207}
208
209
210/*
211 * Parses and splits an ASN.1 "SEQUENCE OF <tag>"
212 */
213static int asn1_get_sequence_of( unsigned char **p,
214 const unsigned char *end,
215 x509_sequence *cur,
216 int tag)
217{
Paul Bakker23986e52011-04-24 08:57:21 +0000218 int ret;
219 size_t len;
Paul Bakker74111d32011-01-15 16:57:55 +0000220 x509_buf *buf;
221
222 /* Get main sequence tag */
223 if( ( ret = asn1_get_tag( p, end, &len,
224 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
225 return( ret );
226
227 if( *p + len != end )
228 return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
229
230 while( *p < end )
231 {
232 buf = &(cur->buf);
233 buf->tag = **p;
234
235 if( ( ret = asn1_get_tag( p, end, &buf->len, tag ) ) != 0 )
236 return( ret );
237
238 buf->p = *p;
239 *p += buf->len;
240
241 /* Allocate and assign next pointer */
242 if (*p < end)
243 {
244 cur->next = (x509_sequence *) malloc(
245 sizeof( x509_sequence ) );
246
247 if( cur->next == NULL )
248 return( 1 );
249
250 cur = cur->next;
251 }
252 }
253
254 /* Set final sequence entry's next pointer to NULL */
255 cur->next = NULL;
256
257 if( *p != end )
258 return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
259
260 return( 0 );
261}
262
Paul Bakker5121ce52009-01-03 21:22:43 +0000263/*
264 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
265 */
266static int x509_get_version( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000267 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000268 int *ver )
269{
Paul Bakker23986e52011-04-24 08:57:21 +0000270 int ret;
271 size_t len;
Paul Bakker5121ce52009-01-03 21:22:43 +0000272
273 if( ( ret = asn1_get_tag( p, end, &len,
274 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) != 0 )
275 {
Paul Bakker40e46942009-01-03 21:51:57 +0000276 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker5121ce52009-01-03 21:22:43 +0000277 return( *ver = 0 );
278
279 return( ret );
280 }
281
282 end = *p + len;
283
284 if( ( ret = asn1_get_int( p, end, ver ) ) != 0 )
Paul Bakker9d781402011-05-09 16:17:09 +0000285 return( POLARSSL_ERR_X509_CERT_INVALID_VERSION + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000286
287 if( *p != end )
Paul Bakker9d781402011-05-09 16:17:09 +0000288 return( POLARSSL_ERR_X509_CERT_INVALID_VERSION +
Paul Bakker40e46942009-01-03 21:51:57 +0000289 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000290
291 return( 0 );
292}
293
294/*
295 * CertificateSerialNumber ::= INTEGER
296 */
297static int x509_get_serial( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000298 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000299 x509_buf *serial )
300{
301 int ret;
302
303 if( ( end - *p ) < 1 )
Paul Bakker9d781402011-05-09 16:17:09 +0000304 return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL +
Paul Bakker40e46942009-01-03 21:51:57 +0000305 POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000306
307 if( **p != ( ASN1_CONTEXT_SPECIFIC | ASN1_PRIMITIVE | 2 ) &&
308 **p != ASN1_INTEGER )
Paul Bakker9d781402011-05-09 16:17:09 +0000309 return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL +
Paul Bakker40e46942009-01-03 21:51:57 +0000310 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000311
312 serial->tag = *(*p)++;
313
314 if( ( ret = asn1_get_len( p, end, &serial->len ) ) != 0 )
Paul Bakker9d781402011-05-09 16:17:09 +0000315 return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000316
317 serial->p = *p;
318 *p += serial->len;
319
320 return( 0 );
321}
322
323/*
324 * AlgorithmIdentifier ::= SEQUENCE {
325 * algorithm OBJECT IDENTIFIER,
326 * parameters ANY DEFINED BY algorithm OPTIONAL }
327 */
328static int x509_get_alg( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000329 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000330 x509_buf *alg )
331{
Paul Bakker23986e52011-04-24 08:57:21 +0000332 int ret;
333 size_t len;
Paul Bakker5121ce52009-01-03 21:22:43 +0000334
335 if( ( ret = asn1_get_tag( p, end, &len,
336 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker9d781402011-05-09 16:17:09 +0000337 return( POLARSSL_ERR_X509_CERT_INVALID_ALG + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000338
339 end = *p + len;
340 alg->tag = **p;
341
342 if( ( ret = asn1_get_tag( p, end, &alg->len, ASN1_OID ) ) != 0 )
Paul Bakker9d781402011-05-09 16:17:09 +0000343 return( POLARSSL_ERR_X509_CERT_INVALID_ALG + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000344
345 alg->p = *p;
346 *p += alg->len;
347
348 if( *p == end )
349 return( 0 );
350
351 /*
352 * assume the algorithm parameters must be NULL
353 */
354 if( ( ret = asn1_get_tag( p, end, &len, ASN1_NULL ) ) != 0 )
Paul Bakker9d781402011-05-09 16:17:09 +0000355 return( POLARSSL_ERR_X509_CERT_INVALID_ALG + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000356
357 if( *p != end )
Paul Bakker9d781402011-05-09 16:17:09 +0000358 return( POLARSSL_ERR_X509_CERT_INVALID_ALG +
Paul Bakker40e46942009-01-03 21:51:57 +0000359 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000360
361 return( 0 );
362}
363
364/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000365 * AttributeTypeAndValue ::= SEQUENCE {
366 * type AttributeType,
367 * value AttributeValue }
368 *
369 * AttributeType ::= OBJECT IDENTIFIER
370 *
371 * AttributeValue ::= ANY DEFINED BY AttributeType
372 */
Paul Bakker400ff6f2011-02-20 10:40:16 +0000373static int x509_get_attr_type_value( unsigned char **p,
374 const unsigned char *end,
375 x509_name *cur )
Paul Bakker5121ce52009-01-03 21:22:43 +0000376{
Paul Bakker23986e52011-04-24 08:57:21 +0000377 int ret;
378 size_t len;
Paul Bakker5121ce52009-01-03 21:22:43 +0000379 x509_buf *oid;
380 x509_buf *val;
381
382 if( ( ret = asn1_get_tag( p, end, &len,
Paul Bakker5121ce52009-01-03 21:22:43 +0000383 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker9d781402011-05-09 16:17:09 +0000384 return( POLARSSL_ERR_X509_CERT_INVALID_NAME + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000385
Paul Bakker5121ce52009-01-03 21:22:43 +0000386 oid = &cur->oid;
387 oid->tag = **p;
388
389 if( ( ret = asn1_get_tag( p, end, &oid->len, ASN1_OID ) ) != 0 )
Paul Bakker9d781402011-05-09 16:17:09 +0000390 return( POLARSSL_ERR_X509_CERT_INVALID_NAME + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000391
392 oid->p = *p;
393 *p += oid->len;
394
395 if( ( end - *p ) < 1 )
Paul Bakker9d781402011-05-09 16:17:09 +0000396 return( POLARSSL_ERR_X509_CERT_INVALID_NAME +
Paul Bakker40e46942009-01-03 21:51:57 +0000397 POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000398
399 if( **p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING &&
400 **p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING &&
401 **p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING )
Paul Bakker9d781402011-05-09 16:17:09 +0000402 return( POLARSSL_ERR_X509_CERT_INVALID_NAME +
Paul Bakker40e46942009-01-03 21:51:57 +0000403 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000404
405 val = &cur->val;
406 val->tag = *(*p)++;
407
408 if( ( ret = asn1_get_len( p, end, &val->len ) ) != 0 )
Paul Bakker9d781402011-05-09 16:17:09 +0000409 return( POLARSSL_ERR_X509_CERT_INVALID_NAME + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000410
411 val->p = *p;
412 *p += val->len;
413
414 cur->next = NULL;
415
Paul Bakker400ff6f2011-02-20 10:40:16 +0000416 return( 0 );
417}
418
419/*
420 * RelativeDistinguishedName ::=
421 * SET OF AttributeTypeAndValue
422 *
423 * AttributeTypeAndValue ::= SEQUENCE {
424 * type AttributeType,
425 * value AttributeValue }
426 *
427 * AttributeType ::= OBJECT IDENTIFIER
428 *
429 * AttributeValue ::= ANY DEFINED BY AttributeType
430 */
431static int x509_get_name( unsigned char **p,
432 const unsigned char *end,
433 x509_name *cur )
434{
Paul Bakker23986e52011-04-24 08:57:21 +0000435 int ret;
436 size_t len;
Paul Bakker400ff6f2011-02-20 10:40:16 +0000437 const unsigned char *end2;
438 x509_name *use;
439
440 if( ( ret = asn1_get_tag( p, end, &len,
441 ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 )
Paul Bakker9d781402011-05-09 16:17:09 +0000442 return( POLARSSL_ERR_X509_CERT_INVALID_NAME + ret );
Paul Bakker400ff6f2011-02-20 10:40:16 +0000443
444 end2 = end;
445 end = *p + len;
446 use = cur;
447
448 do
449 {
450 if( ( ret = x509_get_attr_type_value( p, end, use ) ) != 0 )
451 return( ret );
452
453 if( *p != end )
454 {
455 use->next = (x509_name *) malloc(
456 sizeof( x509_name ) );
457
458 if( use->next == NULL )
459 return( 1 );
460
461 memset( use->next, 0, sizeof( x509_name ) );
462
463 use = use->next;
464 }
465 }
466 while( *p != end );
Paul Bakker5121ce52009-01-03 21:22:43 +0000467
468 /*
469 * recurse until end of SEQUENCE is reached
470 */
471 if( *p == end2 )
472 return( 0 );
473
474 cur->next = (x509_name *) malloc(
475 sizeof( x509_name ) );
476
477 if( cur->next == NULL )
478 return( 1 );
479
480 return( x509_get_name( p, end2, cur->next ) );
481}
482
483/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000484 * Time ::= CHOICE {
485 * utcTime UTCTime,
486 * generalTime GeneralizedTime }
487 */
Paul Bakker91200182010-02-18 21:26:15 +0000488static int x509_get_time( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000489 const unsigned char *end,
Paul Bakkerd98030e2009-05-02 15:13:40 +0000490 x509_time *time )
491{
Paul Bakker23986e52011-04-24 08:57:21 +0000492 int ret;
493 size_t len;
Paul Bakkerd98030e2009-05-02 15:13:40 +0000494 char date[64];
Paul Bakker91200182010-02-18 21:26:15 +0000495 unsigned char tag;
Paul Bakkerd98030e2009-05-02 15:13:40 +0000496
Paul Bakker91200182010-02-18 21:26:15 +0000497 if( ( end - *p ) < 1 )
Paul Bakker9d781402011-05-09 16:17:09 +0000498 return( POLARSSL_ERR_X509_CERT_INVALID_DATE +
499 POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakkerd98030e2009-05-02 15:13:40 +0000500
Paul Bakker91200182010-02-18 21:26:15 +0000501 tag = **p;
Paul Bakkerd98030e2009-05-02 15:13:40 +0000502
Paul Bakker91200182010-02-18 21:26:15 +0000503 if ( tag == ASN1_UTC_TIME )
504 {
505 (*p)++;
506 ret = asn1_get_len( p, end, &len );
507
508 if( ret != 0 )
Paul Bakker9d781402011-05-09 16:17:09 +0000509 return( POLARSSL_ERR_X509_CERT_INVALID_DATE + ret );
Paul Bakkerd98030e2009-05-02 15:13:40 +0000510
Paul Bakker91200182010-02-18 21:26:15 +0000511 memset( date, 0, sizeof( date ) );
Paul Bakker27fdf462011-06-09 13:55:13 +0000512 memcpy( date, *p, ( len < sizeof( date ) - 1 ) ?
513 len : sizeof( date ) - 1 );
Paul Bakkerd98030e2009-05-02 15:13:40 +0000514
Paul Bakker91200182010-02-18 21:26:15 +0000515 if( sscanf( date, "%2d%2d%2d%2d%2d%2d",
516 &time->year, &time->mon, &time->day,
517 &time->hour, &time->min, &time->sec ) < 5 )
518 return( POLARSSL_ERR_X509_CERT_INVALID_DATE );
Paul Bakkerd98030e2009-05-02 15:13:40 +0000519
Paul Bakker400ff6f2011-02-20 10:40:16 +0000520 time->year += 100 * ( time->year < 50 );
Paul Bakker91200182010-02-18 21:26:15 +0000521 time->year += 1900;
522
523 *p += len;
524
525 return( 0 );
526 }
527 else if ( tag == ASN1_GENERALIZED_TIME )
528 {
529 (*p)++;
530 ret = asn1_get_len( p, end, &len );
531
532 if( ret != 0 )
Paul Bakker9d781402011-05-09 16:17:09 +0000533 return( POLARSSL_ERR_X509_CERT_INVALID_DATE + ret );
Paul Bakker91200182010-02-18 21:26:15 +0000534
535 memset( date, 0, sizeof( date ) );
Paul Bakker27fdf462011-06-09 13:55:13 +0000536 memcpy( date, *p, ( len < sizeof( date ) - 1 ) ?
537 len : sizeof( date ) - 1 );
Paul Bakker91200182010-02-18 21:26:15 +0000538
539 if( sscanf( date, "%4d%2d%2d%2d%2d%2d",
540 &time->year, &time->mon, &time->day,
541 &time->hour, &time->min, &time->sec ) < 5 )
542 return( POLARSSL_ERR_X509_CERT_INVALID_DATE );
543
544 *p += len;
545
546 return( 0 );
547 }
548 else
Paul Bakker9d781402011-05-09 16:17:09 +0000549 return( POLARSSL_ERR_X509_CERT_INVALID_DATE + POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakkerd98030e2009-05-02 15:13:40 +0000550}
551
552
553/*
554 * Validity ::= SEQUENCE {
555 * notBefore Time,
556 * notAfter Time }
557 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000558static int x509_get_dates( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000559 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000560 x509_time *from,
561 x509_time *to )
562{
Paul Bakker23986e52011-04-24 08:57:21 +0000563 int ret;
564 size_t len;
Paul Bakker5121ce52009-01-03 21:22:43 +0000565
566 if( ( ret = asn1_get_tag( p, end, &len,
567 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker9d781402011-05-09 16:17:09 +0000568 return( POLARSSL_ERR_X509_CERT_INVALID_DATE + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000569
570 end = *p + len;
571
Paul Bakker91200182010-02-18 21:26:15 +0000572 if( ( ret = x509_get_time( p, end, from ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +0000573 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000574
Paul Bakker91200182010-02-18 21:26:15 +0000575 if( ( ret = x509_get_time( p, end, to ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +0000576 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000577
578 if( *p != end )
Paul Bakker9d781402011-05-09 16:17:09 +0000579 return( POLARSSL_ERR_X509_CERT_INVALID_DATE +
Paul Bakker40e46942009-01-03 21:51:57 +0000580 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000581
582 return( 0 );
583}
584
585/*
586 * SubjectPublicKeyInfo ::= SEQUENCE {
587 * algorithm AlgorithmIdentifier,
588 * subjectPublicKey BIT STRING }
589 */
590static int x509_get_pubkey( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000591 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000592 x509_buf *pk_alg_oid,
593 mpi *N, mpi *E )
594{
Paul Bakker23986e52011-04-24 08:57:21 +0000595 int ret, can_handle;
596 size_t len;
Paul Bakker5121ce52009-01-03 21:22:43 +0000597 unsigned char *end2;
598
599 if( ( ret = x509_get_alg( p, end, pk_alg_oid ) ) != 0 )
600 return( ret );
601
602 /*
603 * only RSA public keys handled at this time
604 */
Paul Bakker400ff6f2011-02-20 10:40:16 +0000605 can_handle = 0;
606
607 if( pk_alg_oid->len == 9 &&
608 memcmp( pk_alg_oid->p, OID_PKCS1_RSA, 9 ) == 0 )
609 can_handle = 1;
610
611 if( pk_alg_oid->len == 9 &&
612 memcmp( pk_alg_oid->p, OID_PKCS1, 8 ) == 0 )
613 {
614 if( pk_alg_oid->p[8] >= 2 && pk_alg_oid->p[8] <= 5 )
615 can_handle = 1;
616
617 if ( pk_alg_oid->p[8] >= 11 && pk_alg_oid->p[8] <= 14 )
618 can_handle = 1;
619 }
620
621 if( pk_alg_oid->len == 5 &&
622 memcmp( pk_alg_oid->p, OID_RSA_SHA_OBS, 5 ) == 0 )
623 can_handle = 1;
624
625 if( can_handle == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000626 return( POLARSSL_ERR_X509_CERT_UNKNOWN_PK_ALG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000627
628 if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 )
Paul Bakker9d781402011-05-09 16:17:09 +0000629 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000630
631 if( ( end - *p ) < 1 )
Paul Bakker9d781402011-05-09 16:17:09 +0000632 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY +
Paul Bakker40e46942009-01-03 21:51:57 +0000633 POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000634
635 end2 = *p + len;
636
637 if( *(*p)++ != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000638 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY );
Paul Bakker5121ce52009-01-03 21:22:43 +0000639
640 /*
641 * RSAPublicKey ::= SEQUENCE {
642 * modulus INTEGER, -- n
643 * publicExponent INTEGER -- e
644 * }
645 */
646 if( ( ret = asn1_get_tag( p, end2, &len,
647 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker9d781402011-05-09 16:17:09 +0000648 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000649
650 if( *p + len != end2 )
Paul Bakker9d781402011-05-09 16:17:09 +0000651 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY +
Paul Bakker40e46942009-01-03 21:51:57 +0000652 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000653
654 if( ( ret = asn1_get_mpi( p, end2, N ) ) != 0 ||
655 ( ret = asn1_get_mpi( p, end2, E ) ) != 0 )
Paul Bakker9d781402011-05-09 16:17:09 +0000656 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000657
658 if( *p != end )
Paul Bakker9d781402011-05-09 16:17:09 +0000659 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY +
Paul Bakker40e46942009-01-03 21:51:57 +0000660 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000661
662 return( 0 );
663}
664
665static int x509_get_sig( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000666 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000667 x509_buf *sig )
668{
Paul Bakker23986e52011-04-24 08:57:21 +0000669 int ret;
670 size_t len;
Paul Bakker5121ce52009-01-03 21:22:43 +0000671
672 sig->tag = **p;
673
674 if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 )
Paul Bakker9d781402011-05-09 16:17:09 +0000675 return( POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000676
Paul Bakker74111d32011-01-15 16:57:55 +0000677
Paul Bakker5121ce52009-01-03 21:22:43 +0000678 if( --len < 1 || *(*p)++ != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000679 return( POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000680
681 sig->len = len;
682 sig->p = *p;
683
684 *p += len;
685
686 return( 0 );
687}
688
689/*
690 * X.509 v2/v3 unique identifier (not parsed)
691 */
692static int x509_get_uid( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000693 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000694 x509_buf *uid, int n )
695{
696 int ret;
697
698 if( *p == end )
699 return( 0 );
700
701 uid->tag = **p;
702
703 if( ( ret = asn1_get_tag( p, end, &uid->len,
704 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | n ) ) != 0 )
705 {
Paul Bakker40e46942009-01-03 21:51:57 +0000706 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker5121ce52009-01-03 21:22:43 +0000707 return( 0 );
708
709 return( ret );
710 }
711
712 uid->p = *p;
713 *p += uid->len;
714
715 return( 0 );
716}
717
718/*
Paul Bakkerd98030e2009-05-02 15:13:40 +0000719 * X.509 Extensions (No parsing of extensions, pointer should
720 * be either manually updated or extensions should be parsed!
Paul Bakker5121ce52009-01-03 21:22:43 +0000721 */
722static int x509_get_ext( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000723 const unsigned char *end,
Paul Bakkerd98030e2009-05-02 15:13:40 +0000724 x509_buf *ext )
Paul Bakker5121ce52009-01-03 21:22:43 +0000725{
Paul Bakker23986e52011-04-24 08:57:21 +0000726 int ret;
727 size_t len;
Paul Bakker5121ce52009-01-03 21:22:43 +0000728
729 if( *p == end )
730 return( 0 );
731
732 ext->tag = **p;
Paul Bakkerff60ee62010-03-16 21:09:09 +0000733
Paul Bakker5121ce52009-01-03 21:22:43 +0000734 if( ( ret = asn1_get_tag( p, end, &ext->len,
735 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000736 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000737
738 ext->p = *p;
739 end = *p + ext->len;
740
741 /*
742 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
743 *
744 * Extension ::= SEQUENCE {
745 * extnID OBJECT IDENTIFIER,
746 * critical BOOLEAN DEFAULT FALSE,
747 * extnValue OCTET STRING }
748 */
749 if( ( ret = asn1_get_tag( p, end, &len,
750 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker9d781402011-05-09 16:17:09 +0000751 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000752
753 if( end != *p + len )
Paul Bakker9d781402011-05-09 16:17:09 +0000754 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
Paul Bakker40e46942009-01-03 21:51:57 +0000755 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000756
Paul Bakkerd98030e2009-05-02 15:13:40 +0000757 return( 0 );
758}
759
760/*
761 * X.509 CRL v2 extensions (no extensions parsed yet.)
762 */
763static int x509_get_crl_ext( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000764 const unsigned char *end,
765 x509_buf *ext )
Paul Bakkerd98030e2009-05-02 15:13:40 +0000766{
Paul Bakker23986e52011-04-24 08:57:21 +0000767 int ret;
768 size_t len;
Paul Bakkerd98030e2009-05-02 15:13:40 +0000769
770 if( ( ret = x509_get_ext( p, end, ext ) ) != 0 )
771 {
772 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
773 return( 0 );
774
775 return( ret );
776 }
777
778 while( *p < end )
779 {
780 if( ( ret = asn1_get_tag( p, end, &len,
781 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker9d781402011-05-09 16:17:09 +0000782 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
Paul Bakkerd98030e2009-05-02 15:13:40 +0000783
784 *p += len;
785 }
786
787 if( *p != end )
Paul Bakker9d781402011-05-09 16:17:09 +0000788 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
Paul Bakkerd98030e2009-05-02 15:13:40 +0000789 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
790
791 return( 0 );
792}
793
Paul Bakker74111d32011-01-15 16:57:55 +0000794static int x509_get_basic_constraints( unsigned char **p,
795 const unsigned char *end,
Paul Bakker74111d32011-01-15 16:57:55 +0000796 int *ca_istrue,
797 int *max_pathlen )
798{
Paul Bakker23986e52011-04-24 08:57:21 +0000799 int ret;
800 size_t len;
Paul Bakker74111d32011-01-15 16:57:55 +0000801
802 /*
803 * BasicConstraints ::= SEQUENCE {
804 * cA BOOLEAN DEFAULT FALSE,
805 * pathLenConstraint INTEGER (0..MAX) OPTIONAL }
806 */
Paul Bakker3cccddb2011-01-16 21:46:31 +0000807 *ca_istrue = 0; /* DEFAULT FALSE */
Paul Bakker74111d32011-01-15 16:57:55 +0000808 *max_pathlen = 0; /* endless */
809
810 if( ( ret = asn1_get_tag( p, end, &len,
811 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker9d781402011-05-09 16:17:09 +0000812 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
Paul Bakker74111d32011-01-15 16:57:55 +0000813
814 if( *p == end )
815 return 0;
816
Paul Bakker3cccddb2011-01-16 21:46:31 +0000817 if( ( ret = asn1_get_bool( p, end, ca_istrue ) ) != 0 )
Paul Bakker74111d32011-01-15 16:57:55 +0000818 {
819 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker3cccddb2011-01-16 21:46:31 +0000820 ret = asn1_get_int( p, end, ca_istrue );
Paul Bakker74111d32011-01-15 16:57:55 +0000821
822 if( ret != 0 )
Paul Bakker9d781402011-05-09 16:17:09 +0000823 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
Paul Bakker74111d32011-01-15 16:57:55 +0000824
Paul Bakker3cccddb2011-01-16 21:46:31 +0000825 if( *ca_istrue != 0 )
826 *ca_istrue = 1;
Paul Bakker74111d32011-01-15 16:57:55 +0000827 }
828
829 if( *p == end )
830 return 0;
831
832 if( ( ret = asn1_get_int( p, end, max_pathlen ) ) != 0 )
Paul Bakker9d781402011-05-09 16:17:09 +0000833 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
Paul Bakker74111d32011-01-15 16:57:55 +0000834
835 if( *p != end )
Paul Bakker9d781402011-05-09 16:17:09 +0000836 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
Paul Bakker74111d32011-01-15 16:57:55 +0000837 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
838
839 (*max_pathlen)++;
840
Paul Bakker74111d32011-01-15 16:57:55 +0000841 return 0;
842}
843
844static int x509_get_ns_cert_type( unsigned char **p,
845 const unsigned char *end,
846 unsigned char *ns_cert_type)
847{
848 int ret;
Paul Bakkerd61e7d92011-01-18 16:17:47 +0000849 x509_bitstring bs = { 0, 0, NULL };
Paul Bakker74111d32011-01-15 16:57:55 +0000850
851 if( ( ret = asn1_get_bitstring( p, end, &bs ) ) != 0 )
Paul Bakker9d781402011-05-09 16:17:09 +0000852 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
Paul Bakker74111d32011-01-15 16:57:55 +0000853
854 if( bs.len != 1 )
Paul Bakker9d781402011-05-09 16:17:09 +0000855 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
Paul Bakker74111d32011-01-15 16:57:55 +0000856 POLARSSL_ERR_ASN1_INVALID_LENGTH );
857
858 /* Get actual bitstring */
859 *ns_cert_type = *bs.p;
860 return 0;
861}
862
863static int x509_get_key_usage( unsigned char **p,
864 const unsigned char *end,
865 unsigned char *key_usage)
866{
867 int ret;
Paul Bakkerd61e7d92011-01-18 16:17:47 +0000868 x509_bitstring bs = { 0, 0, NULL };
Paul Bakker74111d32011-01-15 16:57:55 +0000869
870 if( ( ret = asn1_get_bitstring( p, end, &bs ) ) != 0 )
Paul Bakker9d781402011-05-09 16:17:09 +0000871 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
Paul Bakker74111d32011-01-15 16:57:55 +0000872
873 if( bs.len != 1 )
Paul Bakker9d781402011-05-09 16:17:09 +0000874 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
Paul Bakker74111d32011-01-15 16:57:55 +0000875 POLARSSL_ERR_ASN1_INVALID_LENGTH );
876
877 /* Get actual bitstring */
878 *key_usage = *bs.p;
879 return 0;
880}
881
Paul Bakkerd98030e2009-05-02 15:13:40 +0000882/*
Paul Bakker74111d32011-01-15 16:57:55 +0000883 * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
884 *
885 * KeyPurposeId ::= OBJECT IDENTIFIER
886 */
887static int x509_get_ext_key_usage( unsigned char **p,
888 const unsigned char *end,
889 x509_sequence *ext_key_usage)
890{
891 int ret;
892
893 if( ( ret = asn1_get_sequence_of( p, end, ext_key_usage, ASN1_OID ) ) != 0 )
Paul Bakker9d781402011-05-09 16:17:09 +0000894 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
Paul Bakker74111d32011-01-15 16:57:55 +0000895
896 /* Sequence length must be >= 1 */
897 if( ext_key_usage->buf.p == NULL )
Paul Bakker9d781402011-05-09 16:17:09 +0000898 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
Paul Bakker74111d32011-01-15 16:57:55 +0000899 POLARSSL_ERR_ASN1_INVALID_LENGTH );
900
901 return 0;
902}
903
904/*
905 * X.509 v3 extensions
906 *
907 * TODO: Perform all of the basic constraints tests required by the RFC
908 * TODO: Set values for undetected extensions to a sane default?
909 *
Paul Bakkerd98030e2009-05-02 15:13:40 +0000910 */
911static int x509_get_crt_ext( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000912 const unsigned char *end,
Paul Bakker74111d32011-01-15 16:57:55 +0000913 x509_cert *crt )
Paul Bakkerd98030e2009-05-02 15:13:40 +0000914{
Paul Bakker23986e52011-04-24 08:57:21 +0000915 int ret;
916 size_t len;
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000917 unsigned char *end_ext_data, *end_ext_octet;
Paul Bakkerd98030e2009-05-02 15:13:40 +0000918
Paul Bakker74111d32011-01-15 16:57:55 +0000919 if( ( ret = x509_get_ext( p, end, &crt->v3_ext ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +0000920 {
921 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
922 return( 0 );
923
924 return( ret );
925 }
926
Paul Bakker5121ce52009-01-03 21:22:43 +0000927 while( *p < end )
928 {
Paul Bakker74111d32011-01-15 16:57:55 +0000929 /*
930 * Extension ::= SEQUENCE {
931 * extnID OBJECT IDENTIFIER,
932 * critical BOOLEAN DEFAULT FALSE,
933 * extnValue OCTET STRING }
934 */
935 x509_buf extn_oid = {0, 0, NULL};
936 int is_critical = 0; /* DEFAULT FALSE */
937
Paul Bakker5121ce52009-01-03 21:22:43 +0000938 if( ( ret = asn1_get_tag( p, end, &len,
939 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker9d781402011-05-09 16:17:09 +0000940 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000941
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000942 end_ext_data = *p + len;
943
Paul Bakker74111d32011-01-15 16:57:55 +0000944 /* Get extension ID */
945 extn_oid.tag = **p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000946
Paul Bakker74111d32011-01-15 16:57:55 +0000947 if( ( ret = asn1_get_tag( p, end, &extn_oid.len, ASN1_OID ) ) != 0 )
Paul Bakker9d781402011-05-09 16:17:09 +0000948 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000949
Paul Bakker74111d32011-01-15 16:57:55 +0000950 extn_oid.p = *p;
951 *p += extn_oid.len;
952
953 if( ( end - *p ) < 1 )
Paul Bakker9d781402011-05-09 16:17:09 +0000954 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
Paul Bakker74111d32011-01-15 16:57:55 +0000955 POLARSSL_ERR_ASN1_OUT_OF_DATA );
956
957 /* Get optional critical */
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000958 if( ( ret = asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 &&
Paul Bakker40e46942009-01-03 21:51:57 +0000959 ( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) )
Paul Bakker9d781402011-05-09 16:17:09 +0000960 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000961
Paul Bakker74111d32011-01-15 16:57:55 +0000962 /* Data should be octet string type */
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000963 if( ( ret = asn1_get_tag( p, end_ext_data, &len,
Paul Bakker5121ce52009-01-03 21:22:43 +0000964 ASN1_OCTET_STRING ) ) != 0 )
Paul Bakker9d781402011-05-09 16:17:09 +0000965 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000966
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000967 end_ext_octet = *p + len;
Paul Bakkerff60ee62010-03-16 21:09:09 +0000968
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000969 if( end_ext_octet != end_ext_data )
Paul Bakker9d781402011-05-09 16:17:09 +0000970 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000971 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000972
Paul Bakker74111d32011-01-15 16:57:55 +0000973 /*
974 * Detect supported extensions
975 */
976 if( ( OID_SIZE( OID_BASIC_CONSTRAINTS ) == extn_oid.len ) &&
977 memcmp( extn_oid.p, OID_BASIC_CONSTRAINTS, extn_oid.len ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000978 {
Paul Bakker74111d32011-01-15 16:57:55 +0000979 /* Parse basic constraints */
980 if( ( ret = x509_get_basic_constraints( p, end_ext_octet,
Paul Bakker3cccddb2011-01-16 21:46:31 +0000981 &crt->ca_istrue, &crt->max_pathlen ) ) != 0 )
Paul Bakker74111d32011-01-15 16:57:55 +0000982 return ( ret );
983 crt->ext_types |= EXT_BASIC_CONSTRAINTS;
Paul Bakker5121ce52009-01-03 21:22:43 +0000984 }
Paul Bakker74111d32011-01-15 16:57:55 +0000985 else if( ( OID_SIZE( OID_NS_CERT_TYPE ) == extn_oid.len ) &&
986 memcmp( extn_oid.p, OID_NS_CERT_TYPE, extn_oid.len ) == 0 )
987 {
988 /* Parse netscape certificate type */
989 if( ( ret = x509_get_ns_cert_type( p, end_ext_octet,
990 &crt->ns_cert_type ) ) != 0 )
991 return ( ret );
992 crt->ext_types |= EXT_NS_CERT_TYPE;
993 }
994 else if( ( OID_SIZE( OID_KEY_USAGE ) == extn_oid.len ) &&
995 memcmp( extn_oid.p, OID_KEY_USAGE, extn_oid.len ) == 0 )
996 {
997 /* Parse key usage */
998 if( ( ret = x509_get_key_usage( p, end_ext_octet,
999 &crt->key_usage ) ) != 0 )
1000 return ( ret );
1001 crt->ext_types |= EXT_KEY_USAGE;
1002 }
1003 else if( ( OID_SIZE( OID_EXTENDED_KEY_USAGE ) == extn_oid.len ) &&
1004 memcmp( extn_oid.p, OID_EXTENDED_KEY_USAGE, extn_oid.len ) == 0 )
1005 {
1006 /* Parse extended key usage */
1007 if( ( ret = x509_get_ext_key_usage( p, end_ext_octet,
1008 &crt->ext_key_usage ) ) != 0 )
1009 return ( ret );
1010 crt->ext_types |= EXT_EXTENDED_KEY_USAGE;
1011 }
1012 else
1013 {
1014 /* No parser found, skip extension */
1015 *p = end_ext_octet;
Paul Bakker5121ce52009-01-03 21:22:43 +00001016
Paul Bakker74111d32011-01-15 16:57:55 +00001017 if( is_critical )
1018 {
1019 /* Data is marked as critical: fail */
Paul Bakker9d781402011-05-09 16:17:09 +00001020 return ( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
Paul Bakker74111d32011-01-15 16:57:55 +00001021 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
1022 }
1023 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001024 }
1025
1026 if( *p != end )
Paul Bakker9d781402011-05-09 16:17:09 +00001027 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
Paul Bakker40e46942009-01-03 21:51:57 +00001028 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001029
Paul Bakker5121ce52009-01-03 21:22:43 +00001030 return( 0 );
1031}
1032
1033/*
Paul Bakkerd98030e2009-05-02 15:13:40 +00001034 * X.509 CRL Entries
1035 */
1036static int x509_get_entries( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +00001037 const unsigned char *end,
Paul Bakkerd98030e2009-05-02 15:13:40 +00001038 x509_crl_entry *entry )
1039{
Paul Bakker23986e52011-04-24 08:57:21 +00001040 int ret;
1041 size_t entry_len;
Paul Bakkerd98030e2009-05-02 15:13:40 +00001042 x509_crl_entry *cur_entry = entry;
1043
1044 if( *p == end )
1045 return( 0 );
1046
Paul Bakker9be19372009-07-27 20:21:53 +00001047 if( ( ret = asn1_get_tag( p, end, &entry_len,
Paul Bakkerd98030e2009-05-02 15:13:40 +00001048 ASN1_SEQUENCE | ASN1_CONSTRUCTED ) ) != 0 )
1049 {
1050 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
1051 return( 0 );
1052
1053 return( ret );
1054 }
1055
Paul Bakker9be19372009-07-27 20:21:53 +00001056 end = *p + entry_len;
Paul Bakkerd98030e2009-05-02 15:13:40 +00001057
1058 while( *p < end )
1059 {
Paul Bakker23986e52011-04-24 08:57:21 +00001060 size_t len2;
Paul Bakkerd98030e2009-05-02 15:13:40 +00001061
1062 if( ( ret = asn1_get_tag( p, end, &len2,
1063 ASN1_SEQUENCE | ASN1_CONSTRUCTED ) ) != 0 )
1064 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00001065 return( ret );
1066 }
1067
Paul Bakker9be19372009-07-27 20:21:53 +00001068 cur_entry->raw.tag = **p;
1069 cur_entry->raw.p = *p;
1070 cur_entry->raw.len = len2;
1071
Paul Bakkerd98030e2009-05-02 15:13:40 +00001072 if( ( ret = x509_get_serial( p, end, &cur_entry->serial ) ) != 0 )
1073 return( ret );
1074
Paul Bakker91200182010-02-18 21:26:15 +00001075 if( ( ret = x509_get_time( p, end, &cur_entry->revocation_date ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +00001076 return( ret );
1077
1078 if( ( ret = x509_get_crl_ext( p, end, &cur_entry->entry_ext ) ) != 0 )
1079 return( ret );
1080
Paul Bakker74111d32011-01-15 16:57:55 +00001081 if ( *p < end )
1082 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00001083 cur_entry->next = malloc( sizeof( x509_crl_entry ) );
1084 cur_entry = cur_entry->next;
1085 memset( cur_entry, 0, sizeof( x509_crl_entry ) );
1086 }
1087 }
1088
1089 return( 0 );
1090}
1091
Paul Bakker27d66162010-03-17 06:56:01 +00001092static int x509_get_sig_alg( const x509_buf *sig_oid, int *sig_alg )
1093{
1094 if( sig_oid->len == 9 &&
1095 memcmp( sig_oid->p, OID_PKCS1, 8 ) == 0 )
1096 {
1097 if( sig_oid->p[8] >= 2 && sig_oid->p[8] <= 5 )
1098 {
1099 *sig_alg = sig_oid->p[8];
1100 return( 0 );
1101 }
1102
1103 if ( sig_oid->p[8] >= 11 && sig_oid->p[8] <= 14 )
1104 {
1105 *sig_alg = sig_oid->p[8];
1106 return( 0 );
1107 }
1108
1109 return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
1110 }
Paul Bakker400ff6f2011-02-20 10:40:16 +00001111 if( sig_oid->len == 5 &&
1112 memcmp( sig_oid->p, OID_RSA_SHA_OBS, 5 ) == 0 )
1113 {
1114 *sig_alg = SIG_RSA_SHA1;
1115 return( 0 );
1116 }
Paul Bakker27d66162010-03-17 06:56:01 +00001117
1118 return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
1119}
1120
Paul Bakkerd98030e2009-05-02 15:13:40 +00001121/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001122 * Parse one or more certificates and add them to the chained list
1123 */
Paul Bakker23986e52011-04-24 08:57:21 +00001124int x509parse_crt( x509_cert *chain, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +00001125{
Paul Bakker23986e52011-04-24 08:57:21 +00001126 int ret;
Paul Bakker5690efc2011-05-26 13:16:06 +00001127 size_t len;
Paul Bakker5121ce52009-01-03 21:22:43 +00001128 unsigned char *p, *end;
1129 x509_cert *crt;
Paul Bakker96743fc2011-02-12 14:30:57 +00001130#if defined(POLARSSL_PEM_C)
1131 pem_context pem;
Paul Bakker5690efc2011-05-26 13:16:06 +00001132 size_t use_len;
Paul Bakker96743fc2011-02-12 14:30:57 +00001133#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00001134
1135 crt = chain;
1136
Paul Bakker320a4b52009-03-28 18:52:39 +00001137 /*
1138 * Check for valid input
1139 */
1140 if( crt == NULL || buf == NULL )
1141 return( 1 );
1142
Paul Bakkere9581d62009-03-28 20:29:25 +00001143 while( crt->version != 0 && crt->next != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +00001144 crt = crt->next;
1145
1146 /*
Paul Bakker320a4b52009-03-28 18:52:39 +00001147 * Add new certificate on the end of the chain if needed.
1148 */
Paul Bakkere9581d62009-03-28 20:29:25 +00001149 if ( crt->version != 0 && crt->next == NULL)
Paul Bakker320a4b52009-03-28 18:52:39 +00001150 {
1151 crt->next = (x509_cert *) malloc( sizeof( x509_cert ) );
1152
Paul Bakker7d06ad22009-05-02 15:53:56 +00001153 if( crt->next == NULL )
1154 {
Paul Bakker320a4b52009-03-28 18:52:39 +00001155 x509_free( crt );
Paul Bakker7d06ad22009-05-02 15:53:56 +00001156 return( 1 );
1157 }
Paul Bakker320a4b52009-03-28 18:52:39 +00001158
Paul Bakker7d06ad22009-05-02 15:53:56 +00001159 crt = crt->next;
1160 memset( crt, 0, sizeof( x509_cert ) );
Paul Bakker320a4b52009-03-28 18:52:39 +00001161 }
1162
Paul Bakker96743fc2011-02-12 14:30:57 +00001163#if defined(POLARSSL_PEM_C)
1164 pem_init( &pem );
1165 ret = pem_read_buffer( &pem,
1166 "-----BEGIN CERTIFICATE-----",
1167 "-----END CERTIFICATE-----",
1168 buf, NULL, 0, &use_len );
Paul Bakker5121ce52009-01-03 21:22:43 +00001169
Paul Bakker96743fc2011-02-12 14:30:57 +00001170 if( ret == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001171 {
Paul Bakker96743fc2011-02-12 14:30:57 +00001172 /*
1173 * Was PEM encoded
1174 */
1175 buflen -= use_len;
1176 buf += use_len;
Paul Bakker5121ce52009-01-03 21:22:43 +00001177
1178 /*
Paul Bakker96743fc2011-02-12 14:30:57 +00001179 * Steal PEM buffer
Paul Bakker5121ce52009-01-03 21:22:43 +00001180 */
Paul Bakker96743fc2011-02-12 14:30:57 +00001181 p = pem.buf;
1182 pem.buf = NULL;
1183 len = pem.buflen;
1184 pem_free( &pem );
1185 }
1186 else if( ret != POLARSSL_ERR_PEM_NO_HEADER_PRESENT )
1187 {
1188 pem_free( &pem );
1189 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001190 }
1191 else
1192 {
1193 /*
1194 * nope, copy the raw DER data
1195 */
1196 p = (unsigned char *) malloc( len = buflen );
1197
1198 if( p == NULL )
1199 return( 1 );
1200
1201 memcpy( p, buf, buflen );
1202
1203 buflen = 0;
1204 }
Paul Bakker96743fc2011-02-12 14:30:57 +00001205#else
1206 p = (unsigned char *) malloc( len = buflen );
1207
1208 if( p == NULL )
1209 return( 1 );
1210
1211 memcpy( p, buf, buflen );
1212
1213 buflen = 0;
1214#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00001215
1216 crt->raw.p = p;
1217 crt->raw.len = len;
1218 end = p + len;
1219
1220 /*
1221 * Certificate ::= SEQUENCE {
1222 * tbsCertificate TBSCertificate,
1223 * signatureAlgorithm AlgorithmIdentifier,
1224 * signatureValue BIT STRING }
1225 */
1226 if( ( ret = asn1_get_tag( &p, end, &len,
1227 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1228 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001229 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +00001230 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT );
Paul Bakker5121ce52009-01-03 21:22:43 +00001231 }
1232
Paul Bakker23986e52011-04-24 08:57:21 +00001233 if( len != (size_t) ( end - p ) )
Paul Bakker5121ce52009-01-03 21:22:43 +00001234 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001235 x509_free( crt );
Paul Bakker9d781402011-05-09 16:17:09 +00001236 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
Paul Bakker40e46942009-01-03 21:51:57 +00001237 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001238 }
1239
1240 /*
1241 * TBSCertificate ::= SEQUENCE {
1242 */
1243 crt->tbs.p = p;
1244
1245 if( ( ret = asn1_get_tag( &p, end, &len,
1246 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1247 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001248 x509_free( crt );
Paul Bakker9d781402011-05-09 16:17:09 +00001249 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001250 }
1251
1252 end = p + len;
1253 crt->tbs.len = end - crt->tbs.p;
1254
1255 /*
1256 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
1257 *
1258 * CertificateSerialNumber ::= INTEGER
1259 *
1260 * signature AlgorithmIdentifier
1261 */
1262 if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 ||
1263 ( ret = x509_get_serial( &p, end, &crt->serial ) ) != 0 ||
1264 ( ret = x509_get_alg( &p, end, &crt->sig_oid1 ) ) != 0 )
1265 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001266 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001267 return( ret );
1268 }
1269
1270 crt->version++;
1271
1272 if( crt->version > 3 )
1273 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001274 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +00001275 return( POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION );
Paul Bakker5121ce52009-01-03 21:22:43 +00001276 }
1277
Paul Bakker27d66162010-03-17 06:56:01 +00001278 if( ( ret = x509_get_sig_alg( &crt->sig_oid1, &crt->sig_alg ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001279 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001280 x509_free( crt );
Paul Bakker27d66162010-03-17 06:56:01 +00001281 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001282 }
1283
1284 /*
1285 * issuer Name
1286 */
1287 crt->issuer_raw.p = p;
1288
1289 if( ( ret = asn1_get_tag( &p, end, &len,
1290 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1291 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001292 x509_free( crt );
Paul Bakker9d781402011-05-09 16:17:09 +00001293 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001294 }
1295
1296 if( ( ret = x509_get_name( &p, p + len, &crt->issuer ) ) != 0 )
1297 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001298 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001299 return( ret );
1300 }
1301
1302 crt->issuer_raw.len = p - crt->issuer_raw.p;
1303
1304 /*
1305 * Validity ::= SEQUENCE {
1306 * notBefore Time,
1307 * notAfter Time }
1308 *
1309 */
1310 if( ( ret = x509_get_dates( &p, end, &crt->valid_from,
1311 &crt->valid_to ) ) != 0 )
1312 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001313 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001314 return( ret );
1315 }
1316
1317 /*
1318 * subject Name
1319 */
1320 crt->subject_raw.p = p;
1321
1322 if( ( ret = asn1_get_tag( &p, end, &len,
1323 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1324 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001325 x509_free( crt );
Paul Bakker9d781402011-05-09 16:17:09 +00001326 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001327 }
1328
1329 if( ( ret = x509_get_name( &p, p + len, &crt->subject ) ) != 0 )
1330 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001331 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001332 return( ret );
1333 }
1334
1335 crt->subject_raw.len = p - crt->subject_raw.p;
1336
1337 /*
1338 * SubjectPublicKeyInfo ::= SEQUENCE
1339 * algorithm AlgorithmIdentifier,
1340 * subjectPublicKey BIT STRING }
1341 */
1342 if( ( ret = asn1_get_tag( &p, end, &len,
1343 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1344 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001345 x509_free( crt );
Paul Bakker9d781402011-05-09 16:17:09 +00001346 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001347 }
1348
1349 if( ( ret = x509_get_pubkey( &p, p + len, &crt->pk_oid,
1350 &crt->rsa.N, &crt->rsa.E ) ) != 0 )
1351 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001352 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001353 return( ret );
1354 }
1355
1356 if( ( ret = rsa_check_pubkey( &crt->rsa ) ) != 0 )
1357 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001358 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001359 return( ret );
1360 }
1361
1362 crt->rsa.len = mpi_size( &crt->rsa.N );
1363
1364 /*
1365 * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
1366 * -- If present, version shall be v2 or v3
1367 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
1368 * -- If present, version shall be v2 or v3
1369 * extensions [3] EXPLICIT Extensions OPTIONAL
1370 * -- If present, version shall be v3
1371 */
1372 if( crt->version == 2 || crt->version == 3 )
1373 {
1374 ret = x509_get_uid( &p, end, &crt->issuer_id, 1 );
1375 if( ret != 0 )
1376 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001377 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001378 return( ret );
1379 }
1380 }
1381
1382 if( crt->version == 2 || crt->version == 3 )
1383 {
1384 ret = x509_get_uid( &p, end, &crt->subject_id, 2 );
1385 if( ret != 0 )
1386 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001387 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001388 return( ret );
1389 }
1390 }
1391
1392 if( crt->version == 3 )
1393 {
Paul Bakker74111d32011-01-15 16:57:55 +00001394 ret = x509_get_crt_ext( &p, end, crt);
Paul Bakker5121ce52009-01-03 21:22:43 +00001395 if( ret != 0 )
1396 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001397 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001398 return( ret );
1399 }
1400 }
1401
1402 if( p != end )
1403 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001404 x509_free( crt );
Paul Bakker9d781402011-05-09 16:17:09 +00001405 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
Paul Bakker40e46942009-01-03 21:51:57 +00001406 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001407 }
1408
1409 end = crt->raw.p + crt->raw.len;
1410
1411 /*
1412 * signatureAlgorithm AlgorithmIdentifier,
1413 * signatureValue BIT STRING
1414 */
1415 if( ( ret = x509_get_alg( &p, end, &crt->sig_oid2 ) ) != 0 )
1416 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001417 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001418 return( ret );
1419 }
1420
Paul Bakker320a4b52009-03-28 18:52:39 +00001421 if( memcmp( crt->sig_oid1.p, crt->sig_oid2.p, crt->sig_oid1.len ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001422 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001423 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +00001424 return( POLARSSL_ERR_X509_CERT_SIG_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001425 }
1426
1427 if( ( ret = x509_get_sig( &p, end, &crt->sig ) ) != 0 )
1428 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001429 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001430 return( ret );
1431 }
1432
1433 if( p != end )
1434 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001435 x509_free( crt );
Paul Bakker9d781402011-05-09 16:17:09 +00001436 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
Paul Bakker40e46942009-01-03 21:51:57 +00001437 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001438 }
1439
Paul Bakker5121ce52009-01-03 21:22:43 +00001440 if( buflen > 0 )
Paul Bakker320a4b52009-03-28 18:52:39 +00001441 {
1442 crt->next = (x509_cert *) malloc( sizeof( x509_cert ) );
1443
Paul Bakker7d06ad22009-05-02 15:53:56 +00001444 if( crt->next == NULL )
1445 {
Paul Bakker320a4b52009-03-28 18:52:39 +00001446 x509_free( crt );
Paul Bakker7d06ad22009-05-02 15:53:56 +00001447 return( 1 );
1448 }
Paul Bakker320a4b52009-03-28 18:52:39 +00001449
Paul Bakker7d06ad22009-05-02 15:53:56 +00001450 crt = crt->next;
1451 memset( crt, 0, sizeof( x509_cert ) );
Paul Bakker320a4b52009-03-28 18:52:39 +00001452
Paul Bakker5121ce52009-01-03 21:22:43 +00001453 return( x509parse_crt( crt, buf, buflen ) );
Paul Bakker320a4b52009-03-28 18:52:39 +00001454 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001455
1456 return( 0 );
1457}
1458
1459/*
Paul Bakkerd98030e2009-05-02 15:13:40 +00001460 * Parse one or more CRLs and add them to the chained list
1461 */
Paul Bakker23986e52011-04-24 08:57:21 +00001462int x509parse_crl( x509_crl *chain, const unsigned char *buf, size_t buflen )
Paul Bakkerd98030e2009-05-02 15:13:40 +00001463{
Paul Bakker23986e52011-04-24 08:57:21 +00001464 int ret;
Paul Bakker5690efc2011-05-26 13:16:06 +00001465 size_t len;
Paul Bakkerd98030e2009-05-02 15:13:40 +00001466 unsigned char *p, *end;
1467 x509_crl *crl;
Paul Bakker96743fc2011-02-12 14:30:57 +00001468#if defined(POLARSSL_PEM_C)
Paul Bakker5690efc2011-05-26 13:16:06 +00001469 size_t use_len;
Paul Bakker96743fc2011-02-12 14:30:57 +00001470 pem_context pem;
1471#endif
Paul Bakkerd98030e2009-05-02 15:13:40 +00001472
1473 crl = chain;
1474
1475 /*
1476 * Check for valid input
1477 */
1478 if( crl == NULL || buf == NULL )
1479 return( 1 );
1480
1481 while( crl->version != 0 && crl->next != NULL )
1482 crl = crl->next;
1483
1484 /*
1485 * Add new CRL on the end of the chain if needed.
1486 */
1487 if ( crl->version != 0 && crl->next == NULL)
1488 {
1489 crl->next = (x509_crl *) malloc( sizeof( x509_crl ) );
1490
Paul Bakker7d06ad22009-05-02 15:53:56 +00001491 if( crl->next == NULL )
1492 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00001493 x509_crl_free( crl );
Paul Bakker7d06ad22009-05-02 15:53:56 +00001494 return( 1 );
1495 }
Paul Bakkerd98030e2009-05-02 15:13:40 +00001496
Paul Bakker7d06ad22009-05-02 15:53:56 +00001497 crl = crl->next;
1498 memset( crl, 0, sizeof( x509_crl ) );
Paul Bakkerd98030e2009-05-02 15:13:40 +00001499 }
1500
Paul Bakker96743fc2011-02-12 14:30:57 +00001501#if defined(POLARSSL_PEM_C)
1502 pem_init( &pem );
1503 ret = pem_read_buffer( &pem,
1504 "-----BEGIN X509 CRL-----",
1505 "-----END X509 CRL-----",
1506 buf, NULL, 0, &use_len );
Paul Bakkerd98030e2009-05-02 15:13:40 +00001507
Paul Bakker96743fc2011-02-12 14:30:57 +00001508 if( ret == 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +00001509 {
Paul Bakker96743fc2011-02-12 14:30:57 +00001510 /*
1511 * Was PEM encoded
1512 */
1513 buflen -= use_len;
1514 buf += use_len;
Paul Bakkerd98030e2009-05-02 15:13:40 +00001515
1516 /*
Paul Bakker96743fc2011-02-12 14:30:57 +00001517 * Steal PEM buffer
Paul Bakkerd98030e2009-05-02 15:13:40 +00001518 */
Paul Bakker96743fc2011-02-12 14:30:57 +00001519 p = pem.buf;
1520 pem.buf = NULL;
1521 len = pem.buflen;
1522 pem_free( &pem );
1523 }
1524 else if( ret != POLARSSL_ERR_PEM_NO_HEADER_PRESENT )
1525 {
1526 pem_free( &pem );
1527 return( ret );
Paul Bakkerd98030e2009-05-02 15:13:40 +00001528 }
1529 else
1530 {
1531 /*
1532 * nope, copy the raw DER data
1533 */
1534 p = (unsigned char *) malloc( len = buflen );
1535
1536 if( p == NULL )
1537 return( 1 );
1538
1539 memcpy( p, buf, buflen );
1540
1541 buflen = 0;
1542 }
Paul Bakker96743fc2011-02-12 14:30:57 +00001543#else
1544 p = (unsigned char *) malloc( len = buflen );
1545
1546 if( p == NULL )
1547 return( 1 );
1548
1549 memcpy( p, buf, buflen );
1550
1551 buflen = 0;
1552#endif
Paul Bakkerd98030e2009-05-02 15:13:40 +00001553
1554 crl->raw.p = p;
1555 crl->raw.len = len;
1556 end = p + len;
1557
1558 /*
1559 * CertificateList ::= SEQUENCE {
1560 * tbsCertList TBSCertList,
1561 * signatureAlgorithm AlgorithmIdentifier,
1562 * signatureValue BIT STRING }
1563 */
1564 if( ( ret = asn1_get_tag( &p, end, &len,
1565 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1566 {
1567 x509_crl_free( crl );
1568 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT );
1569 }
1570
Paul Bakker23986e52011-04-24 08:57:21 +00001571 if( len != (size_t) ( end - p ) )
Paul Bakkerd98030e2009-05-02 15:13:40 +00001572 {
1573 x509_crl_free( crl );
Paul Bakker9d781402011-05-09 16:17:09 +00001574 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
Paul Bakkerd98030e2009-05-02 15:13:40 +00001575 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
1576 }
1577
1578 /*
1579 * TBSCertList ::= SEQUENCE {
1580 */
1581 crl->tbs.p = p;
1582
1583 if( ( ret = asn1_get_tag( &p, end, &len,
1584 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1585 {
1586 x509_crl_free( crl );
Paul Bakker9d781402011-05-09 16:17:09 +00001587 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
Paul Bakkerd98030e2009-05-02 15:13:40 +00001588 }
1589
1590 end = p + len;
1591 crl->tbs.len = end - crl->tbs.p;
1592
1593 /*
1594 * Version ::= INTEGER OPTIONAL { v1(0), v2(1) }
1595 * -- if present, MUST be v2
1596 *
1597 * signature AlgorithmIdentifier
1598 */
1599 if( ( ret = x509_get_version( &p, end, &crl->version ) ) != 0 ||
1600 ( ret = x509_get_alg( &p, end, &crl->sig_oid1 ) ) != 0 )
1601 {
1602 x509_crl_free( crl );
1603 return( ret );
1604 }
1605
1606 crl->version++;
1607
1608 if( crl->version > 2 )
1609 {
1610 x509_crl_free( crl );
1611 return( POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION );
1612 }
1613
Paul Bakker27d66162010-03-17 06:56:01 +00001614 if( ( ret = x509_get_sig_alg( &crl->sig_oid1, &crl->sig_alg ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +00001615 {
1616 x509_crl_free( crl );
1617 return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
1618 }
1619
1620 /*
1621 * issuer Name
1622 */
1623 crl->issuer_raw.p = p;
1624
1625 if( ( ret = asn1_get_tag( &p, end, &len,
1626 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1627 {
1628 x509_crl_free( crl );
Paul Bakker9d781402011-05-09 16:17:09 +00001629 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
Paul Bakkerd98030e2009-05-02 15:13:40 +00001630 }
1631
1632 if( ( ret = x509_get_name( &p, p + len, &crl->issuer ) ) != 0 )
1633 {
1634 x509_crl_free( crl );
1635 return( ret );
1636 }
1637
1638 crl->issuer_raw.len = p - crl->issuer_raw.p;
1639
1640 /*
1641 * thisUpdate Time
1642 * nextUpdate Time OPTIONAL
1643 */
Paul Bakker91200182010-02-18 21:26:15 +00001644 if( ( ret = x509_get_time( &p, end, &crl->this_update ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +00001645 {
1646 x509_crl_free( crl );
1647 return( ret );
1648 }
1649
Paul Bakker91200182010-02-18 21:26:15 +00001650 if( ( ret = x509_get_time( &p, end, &crl->next_update ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +00001651 {
Paul Bakker9d781402011-05-09 16:17:09 +00001652 if ( ret != ( POLARSSL_ERR_X509_CERT_INVALID_DATE +
Paul Bakker9be19372009-07-27 20:21:53 +00001653 POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) &&
Paul Bakker9d781402011-05-09 16:17:09 +00001654 ret != ( POLARSSL_ERR_X509_CERT_INVALID_DATE +
Paul Bakker9be19372009-07-27 20:21:53 +00001655 POLARSSL_ERR_ASN1_OUT_OF_DATA ) )
Paul Bakker635f4b42009-07-20 20:34:41 +00001656 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00001657 x509_crl_free( crl );
1658 return( ret );
1659 }
1660 }
1661
1662 /*
1663 * revokedCertificates SEQUENCE OF SEQUENCE {
1664 * userCertificate CertificateSerialNumber,
1665 * revocationDate Time,
1666 * crlEntryExtensions Extensions OPTIONAL
1667 * -- if present, MUST be v2
1668 * } OPTIONAL
1669 */
1670 if( ( ret = x509_get_entries( &p, end, &crl->entry ) ) != 0 )
1671 {
1672 x509_crl_free( crl );
1673 return( ret );
1674 }
1675
1676 /*
1677 * crlExtensions EXPLICIT Extensions OPTIONAL
1678 * -- if present, MUST be v2
1679 */
1680 if( crl->version == 2 )
1681 {
1682 ret = x509_get_crl_ext( &p, end, &crl->crl_ext );
1683
1684 if( ret != 0 )
1685 {
1686 x509_crl_free( crl );
1687 return( ret );
1688 }
1689 }
1690
1691 if( p != end )
1692 {
1693 x509_crl_free( crl );
Paul Bakker9d781402011-05-09 16:17:09 +00001694 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
Paul Bakkerd98030e2009-05-02 15:13:40 +00001695 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
1696 }
1697
1698 end = crl->raw.p + crl->raw.len;
1699
1700 /*
1701 * signatureAlgorithm AlgorithmIdentifier,
1702 * signatureValue BIT STRING
1703 */
1704 if( ( ret = x509_get_alg( &p, end, &crl->sig_oid2 ) ) != 0 )
1705 {
1706 x509_crl_free( crl );
1707 return( ret );
1708 }
1709
1710 if( memcmp( crl->sig_oid1.p, crl->sig_oid2.p, crl->sig_oid1.len ) != 0 )
1711 {
1712 x509_crl_free( crl );
1713 return( POLARSSL_ERR_X509_CERT_SIG_MISMATCH );
1714 }
1715
1716 if( ( ret = x509_get_sig( &p, end, &crl->sig ) ) != 0 )
1717 {
1718 x509_crl_free( crl );
1719 return( ret );
1720 }
1721
1722 if( p != end )
1723 {
1724 x509_crl_free( crl );
Paul Bakker9d781402011-05-09 16:17:09 +00001725 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
Paul Bakkerd98030e2009-05-02 15:13:40 +00001726 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
1727 }
1728
1729 if( buflen > 0 )
1730 {
1731 crl->next = (x509_crl *) malloc( sizeof( x509_crl ) );
1732
Paul Bakker7d06ad22009-05-02 15:53:56 +00001733 if( crl->next == NULL )
1734 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00001735 x509_crl_free( crl );
Paul Bakker7d06ad22009-05-02 15:53:56 +00001736 return( 1 );
1737 }
Paul Bakkerd98030e2009-05-02 15:13:40 +00001738
Paul Bakker7d06ad22009-05-02 15:53:56 +00001739 crl = crl->next;
1740 memset( crl, 0, sizeof( x509_crl ) );
Paul Bakkerd98030e2009-05-02 15:13:40 +00001741
1742 return( x509parse_crl( crl, buf, buflen ) );
1743 }
1744
1745 return( 0 );
1746}
1747
Paul Bakker335db3f2011-04-25 15:28:35 +00001748#if defined(POLARSSL_FS_IO)
Paul Bakkerd98030e2009-05-02 15:13:40 +00001749/*
Paul Bakker2b245eb2009-04-19 18:44:26 +00001750 * Load all data from a file into a given buffer.
1751 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001752int load_file( const char *path, unsigned char **buf, size_t *n )
Paul Bakker2b245eb2009-04-19 18:44:26 +00001753{
Paul Bakkerd98030e2009-05-02 15:13:40 +00001754 FILE *f;
Paul Bakker2b245eb2009-04-19 18:44:26 +00001755
Paul Bakkerd98030e2009-05-02 15:13:40 +00001756 if( ( f = fopen( path, "rb" ) ) == NULL )
1757 return( 1 );
Paul Bakker2b245eb2009-04-19 18:44:26 +00001758
Paul Bakkerd98030e2009-05-02 15:13:40 +00001759 fseek( f, 0, SEEK_END );
1760 *n = (size_t) ftell( f );
1761 fseek( f, 0, SEEK_SET );
Paul Bakker2b245eb2009-04-19 18:44:26 +00001762
Paul Bakkerd98030e2009-05-02 15:13:40 +00001763 if( ( *buf = (unsigned char *) malloc( *n + 1 ) ) == NULL )
1764 return( 1 );
Paul Bakker2b245eb2009-04-19 18:44:26 +00001765
Paul Bakkerd98030e2009-05-02 15:13:40 +00001766 if( fread( *buf, 1, *n, f ) != *n )
1767 {
1768 fclose( f );
1769 free( *buf );
1770 return( 1 );
1771 }
Paul Bakker2b245eb2009-04-19 18:44:26 +00001772
Paul Bakkerd98030e2009-05-02 15:13:40 +00001773 fclose( f );
Paul Bakker2b245eb2009-04-19 18:44:26 +00001774
Paul Bakkerd98030e2009-05-02 15:13:40 +00001775 (*buf)[*n] = '\0';
Paul Bakker2b245eb2009-04-19 18:44:26 +00001776
Paul Bakkerd98030e2009-05-02 15:13:40 +00001777 return( 0 );
Paul Bakker2b245eb2009-04-19 18:44:26 +00001778}
1779
1780/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001781 * Load one or more certificates and add them to the chained list
1782 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001783int x509parse_crtfile( x509_cert *chain, const char *path )
Paul Bakker5121ce52009-01-03 21:22:43 +00001784{
1785 int ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001786 size_t n;
1787 unsigned char *buf;
1788
Paul Bakker2b245eb2009-04-19 18:44:26 +00001789 if ( load_file( path, &buf, &n ) )
Paul Bakker5121ce52009-01-03 21:22:43 +00001790 return( 1 );
1791
Paul Bakker27fdf462011-06-09 13:55:13 +00001792 ret = x509parse_crt( chain, buf, n );
Paul Bakker5121ce52009-01-03 21:22:43 +00001793
1794 memset( buf, 0, n + 1 );
1795 free( buf );
Paul Bakker5121ce52009-01-03 21:22:43 +00001796
1797 return( ret );
1798}
1799
Paul Bakkerd98030e2009-05-02 15:13:40 +00001800/*
1801 * Load one or more CRLs and add them to the chained list
1802 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001803int x509parse_crlfile( x509_crl *chain, const char *path )
Paul Bakkerd98030e2009-05-02 15:13:40 +00001804{
1805 int ret;
1806 size_t n;
1807 unsigned char *buf;
1808
1809 if ( load_file( path, &buf, &n ) )
1810 return( 1 );
1811
Paul Bakker27fdf462011-06-09 13:55:13 +00001812 ret = x509parse_crl( chain, buf, n );
Paul Bakkerd98030e2009-05-02 15:13:40 +00001813
1814 memset( buf, 0, n + 1 );
1815 free( buf );
1816
1817 return( ret );
1818}
1819
Paul Bakker5121ce52009-01-03 21:22:43 +00001820/*
Paul Bakker335db3f2011-04-25 15:28:35 +00001821 * Load and parse a private RSA key
1822 */
1823int x509parse_keyfile( rsa_context *rsa, const char *path, const char *pwd )
1824{
1825 int ret;
1826 size_t n;
1827 unsigned char *buf;
1828
1829 if ( load_file( path, &buf, &n ) )
1830 return( 1 );
1831
1832 if( pwd == NULL )
Paul Bakker27fdf462011-06-09 13:55:13 +00001833 ret = x509parse_key( rsa, buf, n, NULL, 0 );
Paul Bakker335db3f2011-04-25 15:28:35 +00001834 else
Paul Bakker27fdf462011-06-09 13:55:13 +00001835 ret = x509parse_key( rsa, buf, n,
Paul Bakker335db3f2011-04-25 15:28:35 +00001836 (unsigned char *) pwd, strlen( pwd ) );
1837
1838 memset( buf, 0, n + 1 );
1839 free( buf );
1840
1841 return( ret );
1842}
1843
1844/*
1845 * Load and parse a public RSA key
1846 */
1847int x509parse_public_keyfile( rsa_context *rsa, const char *path )
1848{
1849 int ret;
1850 size_t n;
1851 unsigned char *buf;
1852
1853 if ( load_file( path, &buf, &n ) )
1854 return( 1 );
1855
Paul Bakker27fdf462011-06-09 13:55:13 +00001856 ret = x509parse_public_key( rsa, buf, n );
Paul Bakker335db3f2011-04-25 15:28:35 +00001857
1858 memset( buf, 0, n + 1 );
1859 free( buf );
1860
1861 return( ret );
1862}
1863#endif /* POLARSSL_FS_IO */
1864
1865/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001866 * Parse a private RSA key
1867 */
Paul Bakker23986e52011-04-24 08:57:21 +00001868int x509parse_key( rsa_context *rsa, const unsigned char *key, size_t keylen,
1869 const unsigned char *pwd, size_t pwdlen )
Paul Bakker5121ce52009-01-03 21:22:43 +00001870{
Paul Bakker23986e52011-04-24 08:57:21 +00001871 int ret;
1872 size_t len;
Paul Bakker5121ce52009-01-03 21:22:43 +00001873 unsigned char *p, *end;
Paul Bakker96743fc2011-02-12 14:30:57 +00001874#if defined(POLARSSL_PEM_C)
1875 pem_context pem;
Paul Bakker5121ce52009-01-03 21:22:43 +00001876
Paul Bakker96743fc2011-02-12 14:30:57 +00001877 pem_init( &pem );
1878 ret = pem_read_buffer( &pem,
1879 "-----BEGIN RSA PRIVATE KEY-----",
1880 "-----END RSA PRIVATE KEY-----",
1881 key, pwd, pwdlen, &len );
Paul Bakker5121ce52009-01-03 21:22:43 +00001882
Paul Bakker96743fc2011-02-12 14:30:57 +00001883 if( ret == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001884 {
Paul Bakker96743fc2011-02-12 14:30:57 +00001885 /*
1886 * Was PEM encoded
1887 */
1888 keylen = pem.buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +00001889 }
Paul Bakker96743fc2011-02-12 14:30:57 +00001890 else if( ret != POLARSSL_ERR_PEM_NO_HEADER_PRESENT )
Paul Bakkerff60ee62010-03-16 21:09:09 +00001891 {
Paul Bakker96743fc2011-02-12 14:30:57 +00001892 pem_free( &pem );
1893 return( ret );
Paul Bakkerff60ee62010-03-16 21:09:09 +00001894 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001895
Paul Bakker96743fc2011-02-12 14:30:57 +00001896 p = ( ret == 0 ) ? pem.buf : (unsigned char *) key;
1897#else
Paul Bakker5690efc2011-05-26 13:16:06 +00001898 ((void) pwd);
1899 ((void) pwdlen);
Paul Bakker96743fc2011-02-12 14:30:57 +00001900 p = (unsigned char *) key;
1901#endif
1902 end = p + keylen;
1903
Paul Bakker5121ce52009-01-03 21:22:43 +00001904 /*
1905 * RSAPrivateKey ::= SEQUENCE {
1906 * version Version,
1907 * modulus INTEGER, -- n
1908 * publicExponent INTEGER, -- e
1909 * privateExponent INTEGER, -- d
1910 * prime1 INTEGER, -- p
1911 * prime2 INTEGER, -- q
1912 * exponent1 INTEGER, -- d mod (p-1)
1913 * exponent2 INTEGER, -- d mod (q-1)
1914 * coefficient INTEGER, -- (inverse of q) mod p
1915 * otherPrimeInfos OtherPrimeInfos OPTIONAL
1916 * }
1917 */
1918 if( ( ret = asn1_get_tag( &p, end, &len,
1919 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1920 {
Paul Bakker96743fc2011-02-12 14:30:57 +00001921#if defined(POLARSSL_PEM_C)
1922 pem_free( &pem );
1923#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00001924 rsa_free( rsa );
Paul Bakker9d781402011-05-09 16:17:09 +00001925 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001926 }
1927
1928 end = p + len;
1929
1930 if( ( ret = asn1_get_int( &p, end, &rsa->ver ) ) != 0 )
1931 {
Paul Bakker96743fc2011-02-12 14:30:57 +00001932#if defined(POLARSSL_PEM_C)
1933 pem_free( &pem );
1934#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00001935 rsa_free( rsa );
Paul Bakker9d781402011-05-09 16:17:09 +00001936 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001937 }
1938
1939 if( rsa->ver != 0 )
1940 {
Paul Bakker96743fc2011-02-12 14:30:57 +00001941#if defined(POLARSSL_PEM_C)
1942 pem_free( &pem );
1943#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00001944 rsa_free( rsa );
Paul Bakker9d781402011-05-09 16:17:09 +00001945 return( POLARSSL_ERR_X509_KEY_INVALID_VERSION + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001946 }
1947
1948 if( ( ret = asn1_get_mpi( &p, end, &rsa->N ) ) != 0 ||
1949 ( ret = asn1_get_mpi( &p, end, &rsa->E ) ) != 0 ||
1950 ( ret = asn1_get_mpi( &p, end, &rsa->D ) ) != 0 ||
1951 ( ret = asn1_get_mpi( &p, end, &rsa->P ) ) != 0 ||
1952 ( ret = asn1_get_mpi( &p, end, &rsa->Q ) ) != 0 ||
1953 ( ret = asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 ||
1954 ( ret = asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 ||
1955 ( ret = asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 )
1956 {
Paul Bakker96743fc2011-02-12 14:30:57 +00001957#if defined(POLARSSL_PEM_C)
1958 pem_free( &pem );
1959#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00001960 rsa_free( rsa );
Paul Bakker9d781402011-05-09 16:17:09 +00001961 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001962 }
1963
1964 rsa->len = mpi_size( &rsa->N );
1965
1966 if( p != end )
1967 {
Paul Bakker96743fc2011-02-12 14:30:57 +00001968#if defined(POLARSSL_PEM_C)
1969 pem_free( &pem );
1970#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00001971 rsa_free( rsa );
Paul Bakker9d781402011-05-09 16:17:09 +00001972 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT +
Paul Bakker40e46942009-01-03 21:51:57 +00001973 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001974 }
1975
1976 if( ( ret = rsa_check_privkey( rsa ) ) != 0 )
1977 {
Paul Bakker96743fc2011-02-12 14:30:57 +00001978#if defined(POLARSSL_PEM_C)
1979 pem_free( &pem );
1980#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00001981 rsa_free( rsa );
1982 return( ret );
1983 }
1984
Paul Bakker96743fc2011-02-12 14:30:57 +00001985#if defined(POLARSSL_PEM_C)
1986 pem_free( &pem );
1987#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00001988
1989 return( 0 );
1990}
1991
1992/*
Paul Bakker53019ae2011-03-25 13:58:48 +00001993 * Parse a public RSA key
1994 */
Paul Bakker23986e52011-04-24 08:57:21 +00001995int x509parse_public_key( rsa_context *rsa, const unsigned char *key, size_t keylen )
Paul Bakker53019ae2011-03-25 13:58:48 +00001996{
Paul Bakker23986e52011-04-24 08:57:21 +00001997 int ret;
1998 size_t len;
Paul Bakker53019ae2011-03-25 13:58:48 +00001999 unsigned char *p, *end;
2000 x509_buf alg_oid;
2001#if defined(POLARSSL_PEM_C)
2002 pem_context pem;
2003
2004 pem_init( &pem );
2005 ret = pem_read_buffer( &pem,
2006 "-----BEGIN PUBLIC KEY-----",
2007 "-----END PUBLIC KEY-----",
2008 key, NULL, 0, &len );
2009
2010 if( ret == 0 )
2011 {
2012 /*
2013 * Was PEM encoded
2014 */
2015 keylen = pem.buflen;
2016 }
2017 else if( ret != POLARSSL_ERR_PEM_NO_HEADER_PRESENT )
2018 {
2019 pem_free( &pem );
2020 return( ret );
2021 }
2022
2023 p = ( ret == 0 ) ? pem.buf : (unsigned char *) key;
2024#else
2025 p = (unsigned char *) key;
2026#endif
2027 end = p + keylen;
2028
2029 /*
2030 * PublicKeyInfo ::= SEQUENCE {
2031 * algorithm AlgorithmIdentifier,
2032 * PublicKey BIT STRING
2033 * }
2034 *
2035 * AlgorithmIdentifier ::= SEQUENCE {
2036 * algorithm OBJECT IDENTIFIER,
2037 * parameters ANY DEFINED BY algorithm OPTIONAL
2038 * }
2039 *
2040 * RSAPublicKey ::= SEQUENCE {
2041 * modulus INTEGER, -- n
2042 * publicExponent INTEGER -- e
2043 * }
2044 */
2045
2046 if( ( ret = asn1_get_tag( &p, end, &len,
2047 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
2048 {
2049#if defined(POLARSSL_PEM_C)
2050 pem_free( &pem );
2051#endif
2052 rsa_free( rsa );
Paul Bakker9d781402011-05-09 16:17:09 +00002053 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
Paul Bakker53019ae2011-03-25 13:58:48 +00002054 }
2055
2056 if( ( ret = x509_get_pubkey( &p, end, &alg_oid, &rsa->N, &rsa->E ) ) != 0 )
2057 {
2058#if defined(POLARSSL_PEM_C)
2059 pem_free( &pem );
2060#endif
2061 rsa_free( rsa );
Paul Bakker9d781402011-05-09 16:17:09 +00002062 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
Paul Bakker53019ae2011-03-25 13:58:48 +00002063 }
2064
2065 if( ( ret = rsa_check_pubkey( rsa ) ) != 0 )
2066 {
2067#if defined(POLARSSL_PEM_C)
2068 pem_free( &pem );
2069#endif
2070 rsa_free( rsa );
2071 return( ret );
2072 }
2073
2074 rsa->len = mpi_size( &rsa->N );
2075
2076#if defined(POLARSSL_PEM_C)
2077 pem_free( &pem );
2078#endif
2079
2080 return( 0 );
2081}
2082
Paul Bakkereaa89f82011-04-04 21:36:15 +00002083#if defined(POLARSSL_DHM_C)
Paul Bakker53019ae2011-03-25 13:58:48 +00002084/*
Paul Bakker1b57b062011-01-06 15:48:19 +00002085 * Parse DHM parameters
2086 */
Paul Bakker23986e52011-04-24 08:57:21 +00002087int x509parse_dhm( dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen )
Paul Bakker1b57b062011-01-06 15:48:19 +00002088{
Paul Bakker23986e52011-04-24 08:57:21 +00002089 int ret;
2090 size_t len;
Paul Bakker1b57b062011-01-06 15:48:19 +00002091 unsigned char *p, *end;
Paul Bakker96743fc2011-02-12 14:30:57 +00002092#if defined(POLARSSL_PEM_C)
2093 pem_context pem;
Paul Bakker1b57b062011-01-06 15:48:19 +00002094
Paul Bakker96743fc2011-02-12 14:30:57 +00002095 pem_init( &pem );
Paul Bakker1b57b062011-01-06 15:48:19 +00002096
Paul Bakker96743fc2011-02-12 14:30:57 +00002097 ret = pem_read_buffer( &pem,
2098 "-----BEGIN DH PARAMETERS-----",
2099 "-----END DH PARAMETERS-----",
2100 dhmin, NULL, 0, &dhminlen );
2101
2102 if( ret == 0 )
Paul Bakker1b57b062011-01-06 15:48:19 +00002103 {
Paul Bakker96743fc2011-02-12 14:30:57 +00002104 /*
2105 * Was PEM encoded
2106 */
2107 dhminlen = pem.buflen;
Paul Bakker1b57b062011-01-06 15:48:19 +00002108 }
Paul Bakker96743fc2011-02-12 14:30:57 +00002109 else if( ret != POLARSSL_ERR_PEM_NO_HEADER_PRESENT )
Paul Bakker1b57b062011-01-06 15:48:19 +00002110 {
Paul Bakker96743fc2011-02-12 14:30:57 +00002111 pem_free( &pem );
2112 return( ret );
Paul Bakker1b57b062011-01-06 15:48:19 +00002113 }
2114
Paul Bakker96743fc2011-02-12 14:30:57 +00002115 p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
2116#else
2117 p = (unsigned char *) dhmin;
2118#endif
2119 end = p + dhminlen;
2120
Paul Bakker1b57b062011-01-06 15:48:19 +00002121 memset( dhm, 0, sizeof( dhm_context ) );
2122
Paul Bakker1b57b062011-01-06 15:48:19 +00002123 /*
2124 * DHParams ::= SEQUENCE {
2125 * prime INTEGER, -- P
2126 * generator INTEGER, -- g
2127 * }
2128 */
2129 if( ( ret = asn1_get_tag( &p, end, &len,
2130 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
2131 {
Paul Bakker96743fc2011-02-12 14:30:57 +00002132#if defined(POLARSSL_PEM_C)
2133 pem_free( &pem );
2134#endif
Paul Bakker9d781402011-05-09 16:17:09 +00002135 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
Paul Bakker1b57b062011-01-06 15:48:19 +00002136 }
2137
2138 end = p + len;
2139
2140 if( ( ret = asn1_get_mpi( &p, end, &dhm->P ) ) != 0 ||
2141 ( ret = asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
2142 {
Paul Bakker96743fc2011-02-12 14:30:57 +00002143#if defined(POLARSSL_PEM_C)
2144 pem_free( &pem );
2145#endif
Paul Bakker1b57b062011-01-06 15:48:19 +00002146 dhm_free( dhm );
Paul Bakker9d781402011-05-09 16:17:09 +00002147 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
Paul Bakker1b57b062011-01-06 15:48:19 +00002148 }
2149
2150 if( p != end )
2151 {
Paul Bakker96743fc2011-02-12 14:30:57 +00002152#if defined(POLARSSL_PEM_C)
2153 pem_free( &pem );
2154#endif
Paul Bakker1b57b062011-01-06 15:48:19 +00002155 dhm_free( dhm );
Paul Bakker9d781402011-05-09 16:17:09 +00002156 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT +
Paul Bakker1b57b062011-01-06 15:48:19 +00002157 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
2158 }
2159
Paul Bakker96743fc2011-02-12 14:30:57 +00002160#if defined(POLARSSL_PEM_C)
2161 pem_free( &pem );
2162#endif
Paul Bakker1b57b062011-01-06 15:48:19 +00002163
2164 return( 0 );
2165}
2166
Paul Bakker335db3f2011-04-25 15:28:35 +00002167#if defined(POLARSSL_FS_IO)
Paul Bakker1b57b062011-01-06 15:48:19 +00002168/*
2169 * Load and parse a private RSA key
2170 */
2171int x509parse_dhmfile( dhm_context *dhm, const char *path )
2172{
2173 int ret;
2174 size_t n;
2175 unsigned char *buf;
2176
2177 if ( load_file( path, &buf, &n ) )
2178 return( 1 );
2179
Paul Bakker27fdf462011-06-09 13:55:13 +00002180 ret = x509parse_dhm( dhm, buf, n );
Paul Bakker1b57b062011-01-06 15:48:19 +00002181
2182 memset( buf, 0, n + 1 );
2183 free( buf );
2184
2185 return( ret );
2186}
Paul Bakker335db3f2011-04-25 15:28:35 +00002187#endif /* POLARSSL_FS_IO */
Paul Bakkereaa89f82011-04-04 21:36:15 +00002188#endif /* POLARSSL_DHM_C */
Paul Bakker1b57b062011-01-06 15:48:19 +00002189
Paul Bakker5121ce52009-01-03 21:22:43 +00002190#if defined _MSC_VER && !defined snprintf
Paul Bakkerd98030e2009-05-02 15:13:40 +00002191#include <stdarg.h>
2192
2193#if !defined vsnprintf
2194#define vsnprintf _vsnprintf
2195#endif // vsnprintf
2196
2197/*
2198 * Windows _snprintf and _vsnprintf are not compatible to linux versions.
2199 * Result value is not size of buffer needed, but -1 if no fit is possible.
2200 *
2201 * This fuction tries to 'fix' this by at least suggesting enlarging the
2202 * size by 20.
2203 */
2204int compat_snprintf(char *str, size_t size, const char *format, ...)
2205{
2206 va_list ap;
2207 int res = -1;
2208
2209 va_start( ap, format );
2210
2211 res = vsnprintf( str, size, format, ap );
2212
2213 va_end( ap );
2214
2215 // No quick fix possible
2216 if ( res < 0 )
Paul Bakker23986e52011-04-24 08:57:21 +00002217 return( (int) size + 20 );
Paul Bakkerd98030e2009-05-02 15:13:40 +00002218
2219 return res;
2220}
2221
2222#define snprintf compat_snprintf
Paul Bakker5121ce52009-01-03 21:22:43 +00002223#endif
2224
Paul Bakkerd98030e2009-05-02 15:13:40 +00002225#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL -2
2226
2227#define SAFE_SNPRINTF() \
2228{ \
2229 if( ret == -1 ) \
2230 return( -1 ); \
2231 \
Paul Bakker23986e52011-04-24 08:57:21 +00002232 if ( (unsigned int) ret > n ) { \
Paul Bakkerd98030e2009-05-02 15:13:40 +00002233 p[n - 1] = '\0'; \
2234 return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
2235 } \
2236 \
Paul Bakker23986e52011-04-24 08:57:21 +00002237 n -= (unsigned int) ret; \
2238 p += (unsigned int) ret; \
Paul Bakkerd98030e2009-05-02 15:13:40 +00002239}
2240
Paul Bakker5121ce52009-01-03 21:22:43 +00002241/*
2242 * Store the name in printable form into buf; no more
Paul Bakkerd98030e2009-05-02 15:13:40 +00002243 * than size characters will be written
Paul Bakker5121ce52009-01-03 21:22:43 +00002244 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00002245int x509parse_dn_gets( char *buf, size_t size, const x509_name *dn )
Paul Bakker5121ce52009-01-03 21:22:43 +00002246{
Paul Bakker23986e52011-04-24 08:57:21 +00002247 int ret;
2248 size_t i, n;
Paul Bakker5121ce52009-01-03 21:22:43 +00002249 unsigned char c;
Paul Bakkerff60ee62010-03-16 21:09:09 +00002250 const x509_name *name;
Paul Bakker5121ce52009-01-03 21:22:43 +00002251 char s[128], *p;
2252
2253 memset( s, 0, sizeof( s ) );
2254
2255 name = dn;
2256 p = buf;
Paul Bakkerd98030e2009-05-02 15:13:40 +00002257 n = size;
Paul Bakker5121ce52009-01-03 21:22:43 +00002258
2259 while( name != NULL )
2260 {
Paul Bakker74111d32011-01-15 16:57:55 +00002261 if( name != dn )
2262 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00002263 ret = snprintf( p, n, ", " );
2264 SAFE_SNPRINTF();
2265 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002266
2267 if( memcmp( name->oid.p, OID_X520, 2 ) == 0 )
2268 {
2269 switch( name->oid.p[2] )
2270 {
2271 case X520_COMMON_NAME:
Paul Bakkerd98030e2009-05-02 15:13:40 +00002272 ret = snprintf( p, n, "CN=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002273
2274 case X520_COUNTRY:
Paul Bakkerd98030e2009-05-02 15:13:40 +00002275 ret = snprintf( p, n, "C=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002276
2277 case X520_LOCALITY:
Paul Bakkerd98030e2009-05-02 15:13:40 +00002278 ret = snprintf( p, n, "L=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002279
2280 case X520_STATE:
Paul Bakkerd98030e2009-05-02 15:13:40 +00002281 ret = snprintf( p, n, "ST=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002282
2283 case X520_ORGANIZATION:
Paul Bakkerd98030e2009-05-02 15:13:40 +00002284 ret = snprintf( p, n, "O=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002285
2286 case X520_ORG_UNIT:
Paul Bakkerd98030e2009-05-02 15:13:40 +00002287 ret = snprintf( p, n, "OU=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002288
2289 default:
Paul Bakkerd98030e2009-05-02 15:13:40 +00002290 ret = snprintf( p, n, "0x%02X=",
Paul Bakker5121ce52009-01-03 21:22:43 +00002291 name->oid.p[2] );
2292 break;
2293 }
Paul Bakkerd98030e2009-05-02 15:13:40 +00002294 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002295 }
2296 else if( memcmp( name->oid.p, OID_PKCS9, 8 ) == 0 )
2297 {
2298 switch( name->oid.p[8] )
2299 {
2300 case PKCS9_EMAIL:
Paul Bakkerd98030e2009-05-02 15:13:40 +00002301 ret = snprintf( p, n, "emailAddress=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002302
2303 default:
Paul Bakkerd98030e2009-05-02 15:13:40 +00002304 ret = snprintf( p, n, "0x%02X=",
Paul Bakker5121ce52009-01-03 21:22:43 +00002305 name->oid.p[8] );
2306 break;
2307 }
Paul Bakkerd98030e2009-05-02 15:13:40 +00002308 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002309 }
2310 else
Paul Bakker74111d32011-01-15 16:57:55 +00002311 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00002312 ret = snprintf( p, n, "\?\?=" );
Paul Bakker74111d32011-01-15 16:57:55 +00002313 SAFE_SNPRINTF();
Paul Bakkerd98030e2009-05-02 15:13:40 +00002314 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002315
2316 for( i = 0; i < name->val.len; i++ )
2317 {
Paul Bakker27fdf462011-06-09 13:55:13 +00002318 if( i >= sizeof( s ) - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002319 break;
2320
2321 c = name->val.p[i];
2322 if( c < 32 || c == 127 || ( c > 128 && c < 160 ) )
2323 s[i] = '?';
2324 else s[i] = c;
2325 }
2326 s[i] = '\0';
Paul Bakkerd98030e2009-05-02 15:13:40 +00002327 ret = snprintf( p, n, "%s", s );
2328 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002329 name = name->next;
2330 }
2331
Paul Bakker23986e52011-04-24 08:57:21 +00002332 return( (int) ( size - n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002333}
2334
2335/*
Paul Bakkerdd476992011-01-16 21:34:59 +00002336 * Store the serial in printable form into buf; no more
2337 * than size characters will be written
2338 */
2339int x509parse_serial_gets( char *buf, size_t size, const x509_buf *serial )
2340{
Paul Bakker23986e52011-04-24 08:57:21 +00002341 int ret;
2342 size_t i, n, nr;
Paul Bakkerdd476992011-01-16 21:34:59 +00002343 char *p;
2344
2345 p = buf;
2346 n = size;
2347
2348 nr = ( serial->len <= 32 )
2349 ? serial->len : 32;
2350
2351 for( i = 0; i < nr; i++ )
2352 {
2353 ret = snprintf( p, n, "%02X%s",
2354 serial->p[i], ( i < nr - 1 ) ? ":" : "" );
2355 SAFE_SNPRINTF();
2356 }
2357
Paul Bakker23986e52011-04-24 08:57:21 +00002358 return( (int) ( size - n ) );
Paul Bakkerdd476992011-01-16 21:34:59 +00002359}
2360
2361/*
Paul Bakkerd98030e2009-05-02 15:13:40 +00002362 * Return an informational string about the certificate.
Paul Bakker5121ce52009-01-03 21:22:43 +00002363 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00002364int x509parse_cert_info( char *buf, size_t size, const char *prefix,
2365 const x509_cert *crt )
Paul Bakker5121ce52009-01-03 21:22:43 +00002366{
Paul Bakker23986e52011-04-24 08:57:21 +00002367 int ret;
2368 size_t n;
Paul Bakkerd98030e2009-05-02 15:13:40 +00002369 char *p;
Paul Bakker5121ce52009-01-03 21:22:43 +00002370
2371 p = buf;
Paul Bakkerd98030e2009-05-02 15:13:40 +00002372 n = size;
Paul Bakker5121ce52009-01-03 21:22:43 +00002373
Paul Bakkerd98030e2009-05-02 15:13:40 +00002374 ret = snprintf( p, n, "%scert. version : %d\n",
Paul Bakker5121ce52009-01-03 21:22:43 +00002375 prefix, crt->version );
Paul Bakkerd98030e2009-05-02 15:13:40 +00002376 SAFE_SNPRINTF();
2377 ret = snprintf( p, n, "%sserial number : ",
Paul Bakker5121ce52009-01-03 21:22:43 +00002378 prefix );
Paul Bakkerd98030e2009-05-02 15:13:40 +00002379 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002380
Paul Bakkerdd476992011-01-16 21:34:59 +00002381 ret = x509parse_serial_gets( p, n, &crt->serial);
2382 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002383
Paul Bakkerd98030e2009-05-02 15:13:40 +00002384 ret = snprintf( p, n, "\n%sissuer name : ", prefix );
2385 SAFE_SNPRINTF();
2386 ret = x509parse_dn_gets( p, n, &crt->issuer );
2387 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002388
Paul Bakkerd98030e2009-05-02 15:13:40 +00002389 ret = snprintf( p, n, "\n%ssubject name : ", prefix );
2390 SAFE_SNPRINTF();
2391 ret = x509parse_dn_gets( p, n, &crt->subject );
2392 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002393
Paul Bakkerd98030e2009-05-02 15:13:40 +00002394 ret = snprintf( p, n, "\n%sissued on : " \
Paul Bakker5121ce52009-01-03 21:22:43 +00002395 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
2396 crt->valid_from.year, crt->valid_from.mon,
2397 crt->valid_from.day, crt->valid_from.hour,
2398 crt->valid_from.min, crt->valid_from.sec );
Paul Bakkerd98030e2009-05-02 15:13:40 +00002399 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002400
Paul Bakkerd98030e2009-05-02 15:13:40 +00002401 ret = snprintf( p, n, "\n%sexpires on : " \
Paul Bakker5121ce52009-01-03 21:22:43 +00002402 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
2403 crt->valid_to.year, crt->valid_to.mon,
2404 crt->valid_to.day, crt->valid_to.hour,
2405 crt->valid_to.min, crt->valid_to.sec );
Paul Bakkerd98030e2009-05-02 15:13:40 +00002406 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002407
Paul Bakkerd98030e2009-05-02 15:13:40 +00002408 ret = snprintf( p, n, "\n%ssigned using : RSA+", prefix );
2409 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002410
Paul Bakker27d66162010-03-17 06:56:01 +00002411 switch( crt->sig_alg )
Paul Bakker5121ce52009-01-03 21:22:43 +00002412 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00002413 case SIG_RSA_MD2 : ret = snprintf( p, n, "MD2" ); break;
2414 case SIG_RSA_MD4 : ret = snprintf( p, n, "MD4" ); break;
2415 case SIG_RSA_MD5 : ret = snprintf( p, n, "MD5" ); break;
2416 case SIG_RSA_SHA1 : ret = snprintf( p, n, "SHA1" ); break;
2417 case SIG_RSA_SHA224 : ret = snprintf( p, n, "SHA224" ); break;
2418 case SIG_RSA_SHA256 : ret = snprintf( p, n, "SHA256" ); break;
2419 case SIG_RSA_SHA384 : ret = snprintf( p, n, "SHA384" ); break;
2420 case SIG_RSA_SHA512 : ret = snprintf( p, n, "SHA512" ); break;
2421 default: ret = snprintf( p, n, "???" ); break;
2422 }
2423 SAFE_SNPRINTF();
2424
2425 ret = snprintf( p, n, "\n%sRSA key size : %d bits\n", prefix,
Paul Bakkerf4f69682011-04-24 16:08:12 +00002426 (int) crt->rsa.N.n * (int) sizeof( unsigned long ) * 8 );
Paul Bakkerd98030e2009-05-02 15:13:40 +00002427 SAFE_SNPRINTF();
2428
Paul Bakker23986e52011-04-24 08:57:21 +00002429 return( (int) ( size - n ) );
Paul Bakkerd98030e2009-05-02 15:13:40 +00002430}
2431
Paul Bakker74111d32011-01-15 16:57:55 +00002432/* Compare a given OID string with an OID x509_buf * */
2433#define OID_CMP(oid_str, oid_buf) \
2434 ( ( OID_SIZE(oid_str) == (oid_buf)->len ) && \
2435 memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) == 0)
2436
2437/*
2438 * Return an informational string describing the given OID
2439 */
2440const char *x509_oid_get_description( x509_buf *oid )
2441{
2442 if ( oid == NULL )
2443 return ( NULL );
2444
2445 else if( OID_CMP( OID_SERVER_AUTH, oid ) )
2446 return( STRING_SERVER_AUTH );
2447
2448 else if( OID_CMP( OID_CLIENT_AUTH, oid ) )
2449 return( STRING_CLIENT_AUTH );
2450
2451 else if( OID_CMP( OID_CODE_SIGNING, oid ) )
2452 return( STRING_CODE_SIGNING );
2453
2454 else if( OID_CMP( OID_EMAIL_PROTECTION, oid ) )
2455 return( STRING_EMAIL_PROTECTION );
2456
2457 else if( OID_CMP( OID_TIME_STAMPING, oid ) )
2458 return( STRING_TIME_STAMPING );
2459
2460 else if( OID_CMP( OID_OCSP_SIGNING, oid ) )
2461 return( STRING_OCSP_SIGNING );
2462
2463 return( NULL );
2464}
2465
2466/* Return the x.y.z.... style numeric string for the given OID */
2467int x509_oid_get_numeric_string( char *buf, size_t size, x509_buf *oid )
2468{
Paul Bakker23986e52011-04-24 08:57:21 +00002469 int ret;
2470 size_t i, n;
Paul Bakker74111d32011-01-15 16:57:55 +00002471 unsigned int value;
2472 char *p;
2473
2474 p = buf;
2475 n = size;
2476
2477 /* First byte contains first two dots */
2478 if( oid->len > 0 )
2479 {
2480 ret = snprintf( p, n, "%d.%d", oid->p[0]/40, oid->p[0]%40 );
2481 SAFE_SNPRINTF();
2482 }
2483
2484 /* TODO: value can overflow in value. */
2485 value = 0;
Paul Bakker23986e52011-04-24 08:57:21 +00002486 for( i = 1; i < oid->len; i++ )
Paul Bakker74111d32011-01-15 16:57:55 +00002487 {
2488 value <<= 7;
2489 value += oid->p[i] & 0x7F;
2490
2491 if( !( oid->p[i] & 0x80 ) )
2492 {
2493 /* Last byte */
2494 ret = snprintf( p, n, ".%d", value );
2495 SAFE_SNPRINTF();
2496 value = 0;
2497 }
2498 }
2499
Paul Bakker23986e52011-04-24 08:57:21 +00002500 return( (int) ( size - n ) );
Paul Bakker74111d32011-01-15 16:57:55 +00002501}
2502
Paul Bakkerd98030e2009-05-02 15:13:40 +00002503/*
2504 * Return an informational string about the CRL.
2505 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00002506int x509parse_crl_info( char *buf, size_t size, const char *prefix,
2507 const x509_crl *crl )
Paul Bakkerd98030e2009-05-02 15:13:40 +00002508{
Paul Bakker23986e52011-04-24 08:57:21 +00002509 int ret;
2510 size_t i, n, nr;
Paul Bakkerd98030e2009-05-02 15:13:40 +00002511 char *p;
Paul Bakkerff60ee62010-03-16 21:09:09 +00002512 const x509_crl_entry *entry;
Paul Bakkerd98030e2009-05-02 15:13:40 +00002513
2514 p = buf;
2515 n = size;
2516
2517 ret = snprintf( p, n, "%sCRL version : %d",
2518 prefix, crl->version );
2519 SAFE_SNPRINTF();
2520
2521 ret = snprintf( p, n, "\n%sissuer name : ", prefix );
2522 SAFE_SNPRINTF();
2523 ret = x509parse_dn_gets( p, n, &crl->issuer );
2524 SAFE_SNPRINTF();
2525
2526 ret = snprintf( p, n, "\n%sthis update : " \
2527 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
2528 crl->this_update.year, crl->this_update.mon,
2529 crl->this_update.day, crl->this_update.hour,
2530 crl->this_update.min, crl->this_update.sec );
2531 SAFE_SNPRINTF();
2532
2533 ret = snprintf( p, n, "\n%snext update : " \
2534 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
2535 crl->next_update.year, crl->next_update.mon,
2536 crl->next_update.day, crl->next_update.hour,
2537 crl->next_update.min, crl->next_update.sec );
2538 SAFE_SNPRINTF();
2539
2540 entry = &crl->entry;
2541
2542 ret = snprintf( p, n, "\n%sRevoked certificates:",
2543 prefix );
2544 SAFE_SNPRINTF();
2545
Paul Bakker9be19372009-07-27 20:21:53 +00002546 while( entry != NULL && entry->raw.len != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +00002547 {
2548 ret = snprintf( p, n, "\n%sserial number: ",
2549 prefix );
2550 SAFE_SNPRINTF();
2551
2552 nr = ( entry->serial.len <= 32 )
2553 ? entry->serial.len : 32;
2554
Paul Bakker74111d32011-01-15 16:57:55 +00002555 for( i = 0; i < nr; i++ )
2556 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00002557 ret = snprintf( p, n, "%02X%s",
2558 entry->serial.p[i], ( i < nr - 1 ) ? ":" : "" );
2559 SAFE_SNPRINTF();
2560 }
2561
2562 ret = snprintf( p, n, " revocation date: " \
2563 "%04d-%02d-%02d %02d:%02d:%02d",
2564 entry->revocation_date.year, entry->revocation_date.mon,
2565 entry->revocation_date.day, entry->revocation_date.hour,
2566 entry->revocation_date.min, entry->revocation_date.sec );
2567 SAFE_SNPRINTF();
2568
2569 entry = entry->next;
Paul Bakker5121ce52009-01-03 21:22:43 +00002570 }
2571
Paul Bakkerd98030e2009-05-02 15:13:40 +00002572 ret = snprintf( p, n, "\n%ssigned using : RSA+", prefix );
2573 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002574
Paul Bakker27d66162010-03-17 06:56:01 +00002575 switch( crl->sig_alg )
Paul Bakkerd98030e2009-05-02 15:13:40 +00002576 {
2577 case SIG_RSA_MD2 : ret = snprintf( p, n, "MD2" ); break;
2578 case SIG_RSA_MD4 : ret = snprintf( p, n, "MD4" ); break;
2579 case SIG_RSA_MD5 : ret = snprintf( p, n, "MD5" ); break;
2580 case SIG_RSA_SHA1 : ret = snprintf( p, n, "SHA1" ); break;
2581 case SIG_RSA_SHA224 : ret = snprintf( p, n, "SHA224" ); break;
2582 case SIG_RSA_SHA256 : ret = snprintf( p, n, "SHA256" ); break;
2583 case SIG_RSA_SHA384 : ret = snprintf( p, n, "SHA384" ); break;
2584 case SIG_RSA_SHA512 : ret = snprintf( p, n, "SHA512" ); break;
2585 default: ret = snprintf( p, n, "???" ); break;
2586 }
2587 SAFE_SNPRINTF();
2588
Paul Bakker1e27bb22009-07-19 20:25:25 +00002589 ret = snprintf( p, n, "\n" );
2590 SAFE_SNPRINTF();
2591
Paul Bakker23986e52011-04-24 08:57:21 +00002592 return( (int) ( size - n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002593}
2594
2595/*
Paul Bakker40ea7de2009-05-03 10:18:48 +00002596 * Return 0 if the x509_time is still valid, or 1 otherwise.
Paul Bakker5121ce52009-01-03 21:22:43 +00002597 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00002598int x509parse_time_expired( const x509_time *to )
Paul Bakker5121ce52009-01-03 21:22:43 +00002599{
2600 struct tm *lt;
2601 time_t tt;
2602
2603 tt = time( NULL );
2604 lt = localtime( &tt );
2605
Paul Bakker40ea7de2009-05-03 10:18:48 +00002606 if( lt->tm_year > to->year - 1900 )
2607 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002608
Paul Bakker40ea7de2009-05-03 10:18:48 +00002609 if( lt->tm_year == to->year - 1900 &&
2610 lt->tm_mon > to->mon - 1 )
2611 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002612
Paul Bakker40ea7de2009-05-03 10:18:48 +00002613 if( lt->tm_year == to->year - 1900 &&
2614 lt->tm_mon == to->mon - 1 &&
2615 lt->tm_mday > to->day )
2616 return( 1 );
2617
Paul Bakkerb6194992011-01-16 21:40:22 +00002618 if( lt->tm_year == to->year - 1900 &&
2619 lt->tm_mon == to->mon - 1 &&
2620 lt->tm_mday == to->day &&
2621 lt->tm_hour > to->hour - 1)
2622 return( 1 );
2623
2624 if( lt->tm_year == to->year - 1900 &&
2625 lt->tm_mon == to->mon - 1 &&
2626 lt->tm_mday == to->day &&
2627 lt->tm_hour == to->hour - 1 &&
2628 lt->tm_min > to->min - 1 )
2629 return( 1 );
2630
2631 if( lt->tm_year == to->year - 1900 &&
2632 lt->tm_mon == to->mon - 1 &&
2633 lt->tm_mday == to->day &&
2634 lt->tm_hour == to->hour - 1 &&
2635 lt->tm_min == to->min - 1 &&
2636 lt->tm_sec > to->sec - 1 )
2637 return( 1 );
2638
Paul Bakker40ea7de2009-05-03 10:18:48 +00002639 return( 0 );
2640}
2641
2642/*
2643 * Return 1 if the certificate is revoked, or 0 otherwise.
2644 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00002645int x509parse_revoked( const x509_cert *crt, const x509_crl *crl )
Paul Bakker40ea7de2009-05-03 10:18:48 +00002646{
Paul Bakkerff60ee62010-03-16 21:09:09 +00002647 const x509_crl_entry *cur = &crl->entry;
Paul Bakker40ea7de2009-05-03 10:18:48 +00002648
2649 while( cur != NULL && cur->serial.len != 0 )
2650 {
Paul Bakkera056efc2011-01-16 21:38:35 +00002651 if( crt->serial.len == cur->serial.len &&
2652 memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 )
Paul Bakker40ea7de2009-05-03 10:18:48 +00002653 {
2654 if( x509parse_time_expired( &cur->revocation_date ) )
2655 return( 1 );
2656 }
2657
2658 cur = cur->next;
2659 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002660
2661 return( 0 );
2662}
2663
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002664/*
2665 * Wrapper for x509 hashes.
2666 *
Paul Bakker0f5f72e2011-01-18 14:58:55 +00002667 * \param out Buffer to receive the hash (Should be at least 64 bytes)
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002668 */
Paul Bakker23986e52011-04-24 08:57:21 +00002669static void x509_hash( const unsigned char *in, size_t len, int alg,
Paul Bakker5121ce52009-01-03 21:22:43 +00002670 unsigned char *out )
2671{
2672 switch( alg )
2673 {
Paul Bakker40e46942009-01-03 21:51:57 +00002674#if defined(POLARSSL_MD2_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00002675 case SIG_RSA_MD2 : md2( in, len, out ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002676#endif
Paul Bakker40e46942009-01-03 21:51:57 +00002677#if defined(POLARSSL_MD4_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00002678 case SIG_RSA_MD4 : md4( in, len, out ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002679#endif
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002680#if defined(POLARSSL_MD5_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00002681 case SIG_RSA_MD5 : md5( in, len, out ); break;
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002682#endif
2683#if defined(POLARSSL_SHA1_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00002684 case SIG_RSA_SHA1 : sha1( in, len, out ); break;
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002685#endif
Paul Bakker4593aea2009-02-09 22:32:35 +00002686#if defined(POLARSSL_SHA2_C)
2687 case SIG_RSA_SHA224 : sha2( in, len, out, 1 ); break;
2688 case SIG_RSA_SHA256 : sha2( in, len, out, 0 ); break;
2689#endif
Paul Bakkerfe1aea72009-10-03 20:09:14 +00002690#if defined(POLARSSL_SHA4_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00002691 case SIG_RSA_SHA384 : sha4( in, len, out, 1 ); break;
2692 case SIG_RSA_SHA512 : sha4( in, len, out, 0 ); break;
2693#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00002694 default:
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002695 memset( out, '\xFF', 64 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002696 break;
2697 }
2698}
2699
2700/*
Paul Bakker76fd75a2011-01-16 21:12:10 +00002701 * Check that the given certificate is valid accoring to the CRL.
2702 */
2703static int x509parse_verifycrl(x509_cert *crt, x509_cert *ca,
2704 x509_crl *crl_list)
2705{
2706 int flags = 0;
2707 int hash_id;
2708 unsigned char hash[64];
2709
2710 /*
2711 * TODO: What happens if no CRL is present?
2712 * Suggestion: Revocation state should be unknown if no CRL is present.
2713 * For backwards compatibility this is not yet implemented.
2714 */
2715
2716 while( ca != NULL && crl_list != NULL && crl_list->version != 0 )
2717 {
2718 if( crl_list->issuer_raw.len != ca->subject_raw.len ||
2719 memcmp( crl_list->issuer_raw.p, ca->subject_raw.p,
2720 crl_list->issuer_raw.len ) != 0 )
2721 {
2722 crl_list = crl_list->next;
2723 continue;
2724 }
2725
2726 /*
2727 * Check if CRL is correctly signed by the trusted CA
2728 */
2729 hash_id = crl_list->sig_alg;
2730
2731 x509_hash( crl_list->tbs.p, crl_list->tbs.len, hash_id, hash );
2732
2733 if( !rsa_pkcs1_verify( &ca->rsa, RSA_PUBLIC, hash_id,
2734 0, hash, crl_list->sig.p ) == 0 )
2735 {
2736 /*
2737 * CRL is not trusted
2738 */
2739 flags |= BADCRL_NOT_TRUSTED;
2740 break;
2741 }
2742
2743 /*
2744 * Check for validity of CRL (Do not drop out)
2745 */
2746 if( x509parse_time_expired( &crl_list->next_update ) )
2747 flags |= BADCRL_EXPIRED;
2748
2749 /*
2750 * Check if certificate is revoked
2751 */
2752 if( x509parse_revoked(crt, crl_list) )
2753 {
2754 flags |= BADCERT_REVOKED;
2755 break;
2756 }
2757
2758 crl_list = crl_list->next;
2759 }
2760 return flags;
2761}
2762
2763/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002764 * Verify the certificate validity
2765 */
2766int x509parse_verify( x509_cert *crt,
2767 x509_cert *trust_ca,
Paul Bakker40ea7de2009-05-03 10:18:48 +00002768 x509_crl *ca_crl,
Paul Bakkerb63b0af2011-01-13 17:54:59 +00002769 const char *cn, int *flags,
2770 int (*f_vrfy)(void *, x509_cert *, int, int),
2771 void *p_vrfy )
Paul Bakker5121ce52009-01-03 21:22:43 +00002772{
Paul Bakker23986e52011-04-24 08:57:21 +00002773 size_t cn_len;
Paul Bakker5121ce52009-01-03 21:22:43 +00002774 int hash_id;
2775 int pathlen;
Paul Bakker76fd75a2011-01-16 21:12:10 +00002776 x509_cert *parent;
Paul Bakker5121ce52009-01-03 21:22:43 +00002777 x509_name *name;
Paul Bakker4593aea2009-02-09 22:32:35 +00002778 unsigned char hash[64];
Paul Bakker5121ce52009-01-03 21:22:43 +00002779
Paul Bakker40ea7de2009-05-03 10:18:48 +00002780 *flags = 0;
2781
2782 if( x509parse_time_expired( &crt->valid_to ) )
2783 *flags = BADCERT_EXPIRED;
Paul Bakker5121ce52009-01-03 21:22:43 +00002784
2785 if( cn != NULL )
2786 {
2787 name = &crt->subject;
2788 cn_len = strlen( cn );
2789
2790 while( name != NULL )
2791 {
2792 if( memcmp( name->oid.p, OID_CN, 3 ) == 0 &&
2793 memcmp( name->val.p, cn, cn_len ) == 0 &&
2794 name->val.len == cn_len )
2795 break;
2796
2797 name = name->next;
2798 }
2799
2800 if( name == NULL )
2801 *flags |= BADCERT_CN_MISMATCH;
2802 }
2803
Paul Bakker5121ce52009-01-03 21:22:43 +00002804 /*
2805 * Iterate upwards in the given cert chain,
2806 * ignoring any upper cert with CA != TRUE.
2807 */
Paul Bakker76fd75a2011-01-16 21:12:10 +00002808 parent = crt->next;
Paul Bakker5121ce52009-01-03 21:22:43 +00002809
2810 pathlen = 1;
2811
Paul Bakker76fd75a2011-01-16 21:12:10 +00002812 while( parent != NULL && parent->version != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002813 {
Paul Bakker76fd75a2011-01-16 21:12:10 +00002814 if( parent->ca_istrue == 0 ||
2815 crt->issuer_raw.len != parent->subject_raw.len ||
2816 memcmp( crt->issuer_raw.p, parent->subject_raw.p,
Paul Bakker5121ce52009-01-03 21:22:43 +00002817 crt->issuer_raw.len ) != 0 )
2818 {
Paul Bakker76fd75a2011-01-16 21:12:10 +00002819 parent = parent->next;
Paul Bakker5121ce52009-01-03 21:22:43 +00002820 continue;
2821 }
2822
Paul Bakker27d66162010-03-17 06:56:01 +00002823 hash_id = crt->sig_alg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002824
2825 x509_hash( crt->tbs.p, crt->tbs.len, hash_id, hash );
2826
Paul Bakker76fd75a2011-01-16 21:12:10 +00002827 if( rsa_pkcs1_verify( &parent->rsa, RSA_PUBLIC, hash_id, 0, hash,
2828 crt->sig.p ) != 0 )
2829 *flags |= BADCERT_NOT_TRUSTED;
2830
2831 /* Check trusted CA's CRL for the given crt */
2832 *flags |= x509parse_verifycrl(crt, parent, ca_crl);
Paul Bakkerb63b0af2011-01-13 17:54:59 +00002833
2834 /* crt is verified to be a child of the parent cur, call verify callback */
Paul Bakker74111d32011-01-15 16:57:55 +00002835 if( NULL != f_vrfy )
2836 {
Paul Bakker76fd75a2011-01-16 21:12:10 +00002837 if( f_vrfy( p_vrfy, crt, pathlen - 1, ( *flags == 0 ) ) != 0 )
Paul Bakkerb63b0af2011-01-13 17:54:59 +00002838 return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
Paul Bakker76fd75a2011-01-16 21:12:10 +00002839 else
2840 *flags = 0;
Paul Bakkerb63b0af2011-01-13 17:54:59 +00002841 }
Paul Bakker76fd75a2011-01-16 21:12:10 +00002842 else if( *flags != 0 )
2843 return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +00002844
2845 pathlen++;
2846
Paul Bakker76fd75a2011-01-16 21:12:10 +00002847 crt = parent;
2848 parent = crt->next;
Paul Bakker5121ce52009-01-03 21:22:43 +00002849 }
2850
2851 /*
Paul Bakker76fd75a2011-01-16 21:12:10 +00002852 * Attempt to validate topmost cert with our CA chain.
Paul Bakker5121ce52009-01-03 21:22:43 +00002853 */
Paul Bakker76fd75a2011-01-16 21:12:10 +00002854 *flags |= BADCERT_NOT_TRUSTED;
2855
Paul Bakker7c6d4a42009-03-28 20:35:47 +00002856 while( trust_ca != NULL && trust_ca->version != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002857 {
2858 if( crt->issuer_raw.len != trust_ca->subject_raw.len ||
2859 memcmp( crt->issuer_raw.p, trust_ca->subject_raw.p,
2860 crt->issuer_raw.len ) != 0 )
2861 {
2862 trust_ca = trust_ca->next;
2863 continue;
2864 }
2865
2866 if( trust_ca->max_pathlen > 0 &&
2867 trust_ca->max_pathlen < pathlen )
2868 break;
2869
Paul Bakker27d66162010-03-17 06:56:01 +00002870 hash_id = crt->sig_alg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002871
2872 x509_hash( crt->tbs.p, crt->tbs.len, hash_id, hash );
2873
2874 if( rsa_pkcs1_verify( &trust_ca->rsa, RSA_PUBLIC, hash_id,
2875 0, hash, crt->sig.p ) == 0 )
2876 {
2877 /*
2878 * cert. is signed by a trusted CA
2879 */
2880 *flags &= ~BADCERT_NOT_TRUSTED;
2881 break;
2882 }
2883
2884 trust_ca = trust_ca->next;
2885 }
2886
Paul Bakker76fd75a2011-01-16 21:12:10 +00002887 /* Check trusted CA's CRL for the given crt */
2888 *flags |= x509parse_verifycrl( crt, trust_ca, ca_crl );
Paul Bakkerb63b0af2011-01-13 17:54:59 +00002889
2890 /* Verification succeeded, call callback on top cert */
Paul Bakker74111d32011-01-15 16:57:55 +00002891 if( NULL != f_vrfy )
2892 {
Paul Bakker76fd75a2011-01-16 21:12:10 +00002893 if( f_vrfy(p_vrfy, crt, pathlen-1, ( *flags == 0 ) ) != 0 )
Paul Bakkerb63b0af2011-01-13 17:54:59 +00002894 return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
Paul Bakker76fd75a2011-01-16 21:12:10 +00002895 else
2896 *flags = 0;
Paul Bakkerb63b0af2011-01-13 17:54:59 +00002897 }
Paul Bakker76fd75a2011-01-16 21:12:10 +00002898 else if( *flags != 0 )
2899 return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
Paul Bakkerb63b0af2011-01-13 17:54:59 +00002900
Paul Bakker5121ce52009-01-03 21:22:43 +00002901 return( 0 );
2902}
2903
2904/*
2905 * Unallocate all certificate data
2906 */
2907void x509_free( x509_cert *crt )
2908{
2909 x509_cert *cert_cur = crt;
2910 x509_cert *cert_prv;
2911 x509_name *name_cur;
2912 x509_name *name_prv;
Paul Bakker74111d32011-01-15 16:57:55 +00002913 x509_sequence *seq_cur;
2914 x509_sequence *seq_prv;
Paul Bakker5121ce52009-01-03 21:22:43 +00002915
2916 if( crt == NULL )
2917 return;
2918
2919 do
2920 {
2921 rsa_free( &cert_cur->rsa );
2922
2923 name_cur = cert_cur->issuer.next;
2924 while( name_cur != NULL )
2925 {
2926 name_prv = name_cur;
2927 name_cur = name_cur->next;
2928 memset( name_prv, 0, sizeof( x509_name ) );
2929 free( name_prv );
2930 }
2931
2932 name_cur = cert_cur->subject.next;
2933 while( name_cur != NULL )
2934 {
2935 name_prv = name_cur;
2936 name_cur = name_cur->next;
2937 memset( name_prv, 0, sizeof( x509_name ) );
2938 free( name_prv );
2939 }
2940
Paul Bakker74111d32011-01-15 16:57:55 +00002941 seq_cur = cert_cur->ext_key_usage.next;
2942 while( seq_cur != NULL )
2943 {
2944 seq_prv = seq_cur;
2945 seq_cur = seq_cur->next;
2946 memset( seq_prv, 0, sizeof( x509_sequence ) );
2947 free( seq_prv );
2948 }
2949
Paul Bakker5121ce52009-01-03 21:22:43 +00002950 if( cert_cur->raw.p != NULL )
2951 {
2952 memset( cert_cur->raw.p, 0, cert_cur->raw.len );
2953 free( cert_cur->raw.p );
2954 }
2955
2956 cert_cur = cert_cur->next;
2957 }
2958 while( cert_cur != NULL );
2959
2960 cert_cur = crt;
2961 do
2962 {
2963 cert_prv = cert_cur;
2964 cert_cur = cert_cur->next;
2965
2966 memset( cert_prv, 0, sizeof( x509_cert ) );
2967 if( cert_prv != crt )
2968 free( cert_prv );
2969 }
2970 while( cert_cur != NULL );
2971}
2972
Paul Bakkerd98030e2009-05-02 15:13:40 +00002973/*
2974 * Unallocate all CRL data
2975 */
2976void x509_crl_free( x509_crl *crl )
2977{
2978 x509_crl *crl_cur = crl;
2979 x509_crl *crl_prv;
2980 x509_name *name_cur;
2981 x509_name *name_prv;
2982 x509_crl_entry *entry_cur;
2983 x509_crl_entry *entry_prv;
2984
2985 if( crl == NULL )
2986 return;
2987
2988 do
2989 {
2990 name_cur = crl_cur->issuer.next;
2991 while( name_cur != NULL )
2992 {
2993 name_prv = name_cur;
2994 name_cur = name_cur->next;
2995 memset( name_prv, 0, sizeof( x509_name ) );
2996 free( name_prv );
2997 }
2998
2999 entry_cur = crl_cur->entry.next;
3000 while( entry_cur != NULL )
3001 {
3002 entry_prv = entry_cur;
3003 entry_cur = entry_cur->next;
3004 memset( entry_prv, 0, sizeof( x509_crl_entry ) );
3005 free( entry_prv );
3006 }
3007
3008 if( crl_cur->raw.p != NULL )
3009 {
3010 memset( crl_cur->raw.p, 0, crl_cur->raw.len );
3011 free( crl_cur->raw.p );
3012 }
3013
3014 crl_cur = crl_cur->next;
3015 }
3016 while( crl_cur != NULL );
3017
3018 crl_cur = crl;
3019 do
3020 {
3021 crl_prv = crl_cur;
3022 crl_cur = crl_cur->next;
3023
3024 memset( crl_prv, 0, sizeof( x509_crl ) );
3025 if( crl_prv != crl )
3026 free( crl_prv );
3027 }
3028 while( crl_cur != NULL );
3029}
3030
Paul Bakker40e46942009-01-03 21:51:57 +00003031#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00003032
Paul Bakker40e46942009-01-03 21:51:57 +00003033#include "polarssl/certs.h"
Paul Bakker5121ce52009-01-03 21:22:43 +00003034
3035/*
3036 * Checkup routine
3037 */
3038int x509_self_test( int verbose )
3039{
Paul Bakker5690efc2011-05-26 13:16:06 +00003040#if defined(POLARSSL_CERTS_C) && defined(POLARSSL_MD5_C)
Paul Bakker23986e52011-04-24 08:57:21 +00003041 int ret;
3042 int flags;
3043 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +00003044 x509_cert cacert;
3045 x509_cert clicert;
3046 rsa_context rsa;
Paul Bakker5690efc2011-05-26 13:16:06 +00003047#if defined(POLARSSL_DHM_C)
Paul Bakker1b57b062011-01-06 15:48:19 +00003048 dhm_context dhm;
Paul Bakker5690efc2011-05-26 13:16:06 +00003049#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00003050
3051 if( verbose != 0 )
3052 printf( " X.509 certificate load: " );
3053
3054 memset( &clicert, 0, sizeof( x509_cert ) );
3055
3056 ret = x509parse_crt( &clicert, (unsigned char *) test_cli_crt,
3057 strlen( test_cli_crt ) );
3058 if( ret != 0 )
3059 {
3060 if( verbose != 0 )
3061 printf( "failed\n" );
3062
3063 return( ret );
3064 }
3065
3066 memset( &cacert, 0, sizeof( x509_cert ) );
3067
3068 ret = x509parse_crt( &cacert, (unsigned char *) test_ca_crt,
3069 strlen( test_ca_crt ) );
3070 if( ret != 0 )
3071 {
3072 if( verbose != 0 )
3073 printf( "failed\n" );
3074
3075 return( ret );
3076 }
3077
3078 if( verbose != 0 )
3079 printf( "passed\n X.509 private key load: " );
3080
3081 i = strlen( test_ca_key );
3082 j = strlen( test_ca_pwd );
3083
Paul Bakker66b78b22011-03-25 14:22:50 +00003084 rsa_init( &rsa, RSA_PKCS_V15, 0 );
3085
Paul Bakker5121ce52009-01-03 21:22:43 +00003086 if( ( ret = x509parse_key( &rsa,
3087 (unsigned char *) test_ca_key, i,
3088 (unsigned char *) test_ca_pwd, j ) ) != 0 )
3089 {
3090 if( verbose != 0 )
3091 printf( "failed\n" );
3092
3093 return( ret );
3094 }
3095
3096 if( verbose != 0 )
3097 printf( "passed\n X.509 signature verify: ");
3098
Paul Bakker23986e52011-04-24 08:57:21 +00003099 ret = x509parse_verify( &clicert, &cacert, NULL, "PolarSSL Client 2", &flags, NULL, NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00003100 if( ret != 0 )
3101 {
Paul Bakker23986e52011-04-24 08:57:21 +00003102 printf("%02x", flags);
Paul Bakker5121ce52009-01-03 21:22:43 +00003103 if( verbose != 0 )
3104 printf( "failed\n" );
3105
3106 return( ret );
3107 }
3108
Paul Bakker5690efc2011-05-26 13:16:06 +00003109#if defined(POLARSSL_DHM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +00003110 if( verbose != 0 )
Paul Bakker1b57b062011-01-06 15:48:19 +00003111 printf( "passed\n X.509 DHM parameter load: " );
3112
3113 i = strlen( test_dhm_params );
3114 j = strlen( test_ca_pwd );
3115
3116 if( ( ret = x509parse_dhm( &dhm, (unsigned char *) test_dhm_params, i ) ) != 0 )
3117 {
3118 if( verbose != 0 )
3119 printf( "failed\n" );
3120
3121 return( ret );
3122 }
3123
3124 if( verbose != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003125 printf( "passed\n\n" );
Paul Bakker5690efc2011-05-26 13:16:06 +00003126#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00003127
3128 x509_free( &cacert );
3129 x509_free( &clicert );
3130 rsa_free( &rsa );
Paul Bakker5690efc2011-05-26 13:16:06 +00003131#if defined(POLARSSL_DHM_C)
Paul Bakker1b57b062011-01-06 15:48:19 +00003132 dhm_free( &dhm );
Paul Bakker5690efc2011-05-26 13:16:06 +00003133#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00003134
3135 return( 0 );
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00003136#else
3137 ((void) verbose);
3138 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
3139#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00003140}
3141
3142#endif
3143
3144#endif