blob: c6a9245afb99146234a3c803ef3c8e29a7edac2f [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>
54#include <stdio.h>
55#include <time.h>
56
57/*
58 * ASN.1 DER decoding routines
59 */
60static int asn1_get_len( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +000061 const unsigned char *end,
Paul Bakker23986e52011-04-24 08:57:21 +000062 size_t *len )
Paul Bakker5121ce52009-01-03 21:22:43 +000063{
64 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +000065 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000066
67 if( ( **p & 0x80 ) == 0 )
68 *len = *(*p)++;
69 else
70 {
71 switch( **p & 0x7F )
72 {
73 case 1:
74 if( ( end - *p ) < 2 )
Paul Bakker40e46942009-01-03 21:51:57 +000075 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000076
77 *len = (*p)[1];
78 (*p) += 2;
79 break;
80
81 case 2:
82 if( ( end - *p ) < 3 )
Paul Bakker40e46942009-01-03 21:51:57 +000083 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000084
85 *len = ( (*p)[1] << 8 ) | (*p)[2];
86 (*p) += 3;
87 break;
88
89 default:
Paul Bakker40e46942009-01-03 21:51:57 +000090 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
Paul Bakker5121ce52009-01-03 21:22:43 +000091 break;
92 }
93 }
94
Paul Bakker23986e52011-04-24 08:57:21 +000095 if( *len > (size_t) ( end - *p ) )
Paul Bakker40e46942009-01-03 21:51:57 +000096 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000097
98 return( 0 );
99}
100
101static int asn1_get_tag( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000102 const unsigned char *end,
Paul Bakker23986e52011-04-24 08:57:21 +0000103 size_t *len, int tag )
Paul Bakker5121ce52009-01-03 21:22:43 +0000104{
105 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000106 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000107
108 if( **p != tag )
Paul Bakker40e46942009-01-03 21:51:57 +0000109 return( POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000110
111 (*p)++;
112
113 return( asn1_get_len( p, end, len ) );
114}
115
116static int asn1_get_bool( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000117 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000118 int *val )
119{
Paul Bakker23986e52011-04-24 08:57:21 +0000120 int ret;
121 size_t len;
Paul Bakker5121ce52009-01-03 21:22:43 +0000122
123 if( ( ret = asn1_get_tag( p, end, &len, ASN1_BOOLEAN ) ) != 0 )
124 return( ret );
125
126 if( len != 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000127 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000128
129 *val = ( **p != 0 ) ? 1 : 0;
130 (*p)++;
131
132 return( 0 );
133}
134
135static int asn1_get_int( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000136 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000137 int *val )
138{
Paul Bakker23986e52011-04-24 08:57:21 +0000139 int ret;
140 size_t len;
Paul Bakker5121ce52009-01-03 21:22:43 +0000141
142 if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
143 return( ret );
144
145 if( len > (int) sizeof( int ) || ( **p & 0x80 ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000146 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000147
148 *val = 0;
149
150 while( len-- > 0 )
151 {
152 *val = ( *val << 8 ) | **p;
153 (*p)++;
154 }
155
156 return( 0 );
157}
158
159static int asn1_get_mpi( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000160 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000161 mpi *X )
162{
Paul Bakker23986e52011-04-24 08:57:21 +0000163 int ret;
164 size_t len;
Paul Bakker5121ce52009-01-03 21:22:43 +0000165
166 if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
167 return( ret );
168
169 ret = mpi_read_binary( X, *p, len );
170
171 *p += len;
172
173 return( ret );
174}
175
Paul Bakker74111d32011-01-15 16:57:55 +0000176static int asn1_get_bitstring( unsigned char **p, const unsigned char *end,
177 x509_bitstring *bs)
178{
179 int ret;
180
181 /* Certificate type is a single byte bitstring */
182 if( ( ret = asn1_get_tag( p, end, &bs->len, ASN1_BIT_STRING ) ) != 0 )
183 return( ret );
184
185 /* Check length, subtract one for actual bit string length */
186 if ( bs->len < 1 )
187 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
188 bs->len -= 1;
189
190 /* Get number of unused bits, ensure unused bits <= 7 */
191 bs->unused_bits = **p;
192 if( bs->unused_bits > 7 )
193 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
194 (*p)++;
195
196 /* Get actual bitstring */
197 bs->p = *p;
198 *p += bs->len;
199
200 if( *p != end )
201 return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
202
203 return 0;
204}
205
206
207/*
208 * Parses and splits an ASN.1 "SEQUENCE OF <tag>"
209 */
210static int asn1_get_sequence_of( unsigned char **p,
211 const unsigned char *end,
212 x509_sequence *cur,
213 int tag)
214{
Paul Bakker23986e52011-04-24 08:57:21 +0000215 int ret;
216 size_t len;
Paul Bakker74111d32011-01-15 16:57:55 +0000217 x509_buf *buf;
218
219 /* Get main sequence tag */
220 if( ( ret = asn1_get_tag( p, end, &len,
221 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
222 return( ret );
223
224 if( *p + len != end )
225 return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
226
227 while( *p < end )
228 {
229 buf = &(cur->buf);
230 buf->tag = **p;
231
232 if( ( ret = asn1_get_tag( p, end, &buf->len, tag ) ) != 0 )
233 return( ret );
234
235 buf->p = *p;
236 *p += buf->len;
237
238 /* Allocate and assign next pointer */
239 if (*p < end)
240 {
241 cur->next = (x509_sequence *) malloc(
242 sizeof( x509_sequence ) );
243
244 if( cur->next == NULL )
245 return( 1 );
246
247 cur = cur->next;
248 }
249 }
250
251 /* Set final sequence entry's next pointer to NULL */
252 cur->next = NULL;
253
254 if( *p != end )
255 return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
256
257 return( 0 );
258}
259
Paul Bakker5121ce52009-01-03 21:22:43 +0000260/*
261 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
262 */
263static int x509_get_version( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000264 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000265 int *ver )
266{
Paul Bakker23986e52011-04-24 08:57:21 +0000267 int ret;
268 size_t len;
Paul Bakker5121ce52009-01-03 21:22:43 +0000269
270 if( ( ret = asn1_get_tag( p, end, &len,
271 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) != 0 )
272 {
Paul Bakker40e46942009-01-03 21:51:57 +0000273 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker5121ce52009-01-03 21:22:43 +0000274 return( *ver = 0 );
275
276 return( ret );
277 }
278
279 end = *p + len;
280
281 if( ( ret = asn1_get_int( p, end, ver ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000282 return( POLARSSL_ERR_X509_CERT_INVALID_VERSION | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000283
284 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000285 return( POLARSSL_ERR_X509_CERT_INVALID_VERSION |
286 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000287
288 return( 0 );
289}
290
291/*
292 * CertificateSerialNumber ::= INTEGER
293 */
294static int x509_get_serial( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000295 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000296 x509_buf *serial )
297{
298 int ret;
299
300 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000301 return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL |
302 POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000303
304 if( **p != ( ASN1_CONTEXT_SPECIFIC | ASN1_PRIMITIVE | 2 ) &&
305 **p != ASN1_INTEGER )
Paul Bakker40e46942009-01-03 21:51:57 +0000306 return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL |
307 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000308
309 serial->tag = *(*p)++;
310
311 if( ( ret = asn1_get_len( p, end, &serial->len ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000312 return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000313
314 serial->p = *p;
315 *p += serial->len;
316
317 return( 0 );
318}
319
320/*
321 * AlgorithmIdentifier ::= SEQUENCE {
322 * algorithm OBJECT IDENTIFIER,
323 * parameters ANY DEFINED BY algorithm OPTIONAL }
324 */
325static int x509_get_alg( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000326 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000327 x509_buf *alg )
328{
Paul Bakker23986e52011-04-24 08:57:21 +0000329 int ret;
330 size_t len;
Paul Bakker5121ce52009-01-03 21:22:43 +0000331
332 if( ( ret = asn1_get_tag( p, end, &len,
333 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000334 return( POLARSSL_ERR_X509_CERT_INVALID_ALG | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000335
336 end = *p + len;
337 alg->tag = **p;
338
339 if( ( ret = asn1_get_tag( p, end, &alg->len, ASN1_OID ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000340 return( POLARSSL_ERR_X509_CERT_INVALID_ALG | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000341
342 alg->p = *p;
343 *p += alg->len;
344
345 if( *p == end )
346 return( 0 );
347
348 /*
349 * assume the algorithm parameters must be NULL
350 */
351 if( ( ret = asn1_get_tag( p, end, &len, ASN1_NULL ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000352 return( POLARSSL_ERR_X509_CERT_INVALID_ALG | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000353
354 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000355 return( POLARSSL_ERR_X509_CERT_INVALID_ALG |
356 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000357
358 return( 0 );
359}
360
361/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000362 * AttributeTypeAndValue ::= SEQUENCE {
363 * type AttributeType,
364 * value AttributeValue }
365 *
366 * AttributeType ::= OBJECT IDENTIFIER
367 *
368 * AttributeValue ::= ANY DEFINED BY AttributeType
369 */
Paul Bakker400ff6f2011-02-20 10:40:16 +0000370static int x509_get_attr_type_value( unsigned char **p,
371 const unsigned char *end,
372 x509_name *cur )
Paul Bakker5121ce52009-01-03 21:22:43 +0000373{
Paul Bakker23986e52011-04-24 08:57:21 +0000374 int ret;
375 size_t len;
Paul Bakker5121ce52009-01-03 21:22:43 +0000376 x509_buf *oid;
377 x509_buf *val;
378
379 if( ( ret = asn1_get_tag( p, end, &len,
Paul Bakker5121ce52009-01-03 21:22:43 +0000380 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000381 return( POLARSSL_ERR_X509_CERT_INVALID_NAME | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000382
Paul Bakker5121ce52009-01-03 21:22:43 +0000383 oid = &cur->oid;
384 oid->tag = **p;
385
386 if( ( ret = asn1_get_tag( p, end, &oid->len, ASN1_OID ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000387 return( POLARSSL_ERR_X509_CERT_INVALID_NAME | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000388
389 oid->p = *p;
390 *p += oid->len;
391
392 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000393 return( POLARSSL_ERR_X509_CERT_INVALID_NAME |
394 POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000395
396 if( **p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING &&
397 **p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING &&
398 **p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING )
Paul Bakker40e46942009-01-03 21:51:57 +0000399 return( POLARSSL_ERR_X509_CERT_INVALID_NAME |
400 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000401
402 val = &cur->val;
403 val->tag = *(*p)++;
404
405 if( ( ret = asn1_get_len( p, end, &val->len ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000406 return( POLARSSL_ERR_X509_CERT_INVALID_NAME | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000407
408 val->p = *p;
409 *p += val->len;
410
411 cur->next = NULL;
412
Paul Bakker400ff6f2011-02-20 10:40:16 +0000413 return( 0 );
414}
415
416/*
417 * RelativeDistinguishedName ::=
418 * SET OF AttributeTypeAndValue
419 *
420 * AttributeTypeAndValue ::= SEQUENCE {
421 * type AttributeType,
422 * value AttributeValue }
423 *
424 * AttributeType ::= OBJECT IDENTIFIER
425 *
426 * AttributeValue ::= ANY DEFINED BY AttributeType
427 */
428static int x509_get_name( unsigned char **p,
429 const unsigned char *end,
430 x509_name *cur )
431{
Paul Bakker23986e52011-04-24 08:57:21 +0000432 int ret;
433 size_t len;
Paul Bakker400ff6f2011-02-20 10:40:16 +0000434 const unsigned char *end2;
435 x509_name *use;
436
437 if( ( ret = asn1_get_tag( p, end, &len,
438 ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 )
439 return( POLARSSL_ERR_X509_CERT_INVALID_NAME | ret );
440
441 end2 = end;
442 end = *p + len;
443 use = cur;
444
445 do
446 {
447 if( ( ret = x509_get_attr_type_value( p, end, use ) ) != 0 )
448 return( ret );
449
450 if( *p != end )
451 {
452 use->next = (x509_name *) malloc(
453 sizeof( x509_name ) );
454
455 if( use->next == NULL )
456 return( 1 );
457
458 memset( use->next, 0, sizeof( x509_name ) );
459
460 use = use->next;
461 }
462 }
463 while( *p != end );
Paul Bakker5121ce52009-01-03 21:22:43 +0000464
465 /*
466 * recurse until end of SEQUENCE is reached
467 */
468 if( *p == end2 )
469 return( 0 );
470
471 cur->next = (x509_name *) malloc(
472 sizeof( x509_name ) );
473
474 if( cur->next == NULL )
475 return( 1 );
476
477 return( x509_get_name( p, end2, cur->next ) );
478}
479
480/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000481 * Time ::= CHOICE {
482 * utcTime UTCTime,
483 * generalTime GeneralizedTime }
484 */
Paul Bakker91200182010-02-18 21:26:15 +0000485static int x509_get_time( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000486 const unsigned char *end,
Paul Bakkerd98030e2009-05-02 15:13:40 +0000487 x509_time *time )
488{
Paul Bakker23986e52011-04-24 08:57:21 +0000489 int ret;
490 size_t len;
Paul Bakkerd98030e2009-05-02 15:13:40 +0000491 char date[64];
Paul Bakker91200182010-02-18 21:26:15 +0000492 unsigned char tag;
Paul Bakkerd98030e2009-05-02 15:13:40 +0000493
Paul Bakker91200182010-02-18 21:26:15 +0000494 if( ( end - *p ) < 1 )
495 return( POLARSSL_ERR_X509_CERT_INVALID_DATE | POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakkerd98030e2009-05-02 15:13:40 +0000496
Paul Bakker91200182010-02-18 21:26:15 +0000497 tag = **p;
Paul Bakkerd98030e2009-05-02 15:13:40 +0000498
Paul Bakker91200182010-02-18 21:26:15 +0000499 if ( tag == ASN1_UTC_TIME )
500 {
501 (*p)++;
502 ret = asn1_get_len( p, end, &len );
503
504 if( ret != 0 )
505 return( POLARSSL_ERR_X509_CERT_INVALID_DATE | ret );
Paul Bakkerd98030e2009-05-02 15:13:40 +0000506
Paul Bakker91200182010-02-18 21:26:15 +0000507 memset( date, 0, sizeof( date ) );
508 memcpy( date, *p, ( len < (int) sizeof( date ) - 1 ) ?
509 len : (int) sizeof( date ) - 1 );
Paul Bakkerd98030e2009-05-02 15:13:40 +0000510
Paul Bakker91200182010-02-18 21:26:15 +0000511 if( sscanf( date, "%2d%2d%2d%2d%2d%2d",
512 &time->year, &time->mon, &time->day,
513 &time->hour, &time->min, &time->sec ) < 5 )
514 return( POLARSSL_ERR_X509_CERT_INVALID_DATE );
Paul Bakkerd98030e2009-05-02 15:13:40 +0000515
Paul Bakker400ff6f2011-02-20 10:40:16 +0000516 time->year += 100 * ( time->year < 50 );
Paul Bakker91200182010-02-18 21:26:15 +0000517 time->year += 1900;
518
519 *p += len;
520
521 return( 0 );
522 }
523 else if ( tag == ASN1_GENERALIZED_TIME )
524 {
525 (*p)++;
526 ret = asn1_get_len( p, end, &len );
527
528 if( ret != 0 )
529 return( POLARSSL_ERR_X509_CERT_INVALID_DATE | ret );
530
531 memset( date, 0, sizeof( date ) );
532 memcpy( date, *p, ( len < (int) sizeof( date ) - 1 ) ?
533 len : (int) sizeof( date ) - 1 );
534
535 if( sscanf( date, "%4d%2d%2d%2d%2d%2d",
536 &time->year, &time->mon, &time->day,
537 &time->hour, &time->min, &time->sec ) < 5 )
538 return( POLARSSL_ERR_X509_CERT_INVALID_DATE );
539
540 *p += len;
541
542 return( 0 );
543 }
544 else
545 return( POLARSSL_ERR_X509_CERT_INVALID_DATE | POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakkerd98030e2009-05-02 15:13:40 +0000546}
547
548
549/*
550 * Validity ::= SEQUENCE {
551 * notBefore Time,
552 * notAfter Time }
553 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000554static int x509_get_dates( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000555 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000556 x509_time *from,
557 x509_time *to )
558{
Paul Bakker23986e52011-04-24 08:57:21 +0000559 int ret;
560 size_t len;
Paul Bakker5121ce52009-01-03 21:22:43 +0000561
562 if( ( ret = asn1_get_tag( p, end, &len,
563 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000564 return( POLARSSL_ERR_X509_CERT_INVALID_DATE | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000565
566 end = *p + len;
567
Paul Bakker91200182010-02-18 21:26:15 +0000568 if( ( ret = x509_get_time( p, end, from ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +0000569 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000570
Paul Bakker91200182010-02-18 21:26:15 +0000571 if( ( ret = x509_get_time( p, end, to ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +0000572 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000573
574 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000575 return( POLARSSL_ERR_X509_CERT_INVALID_DATE |
576 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000577
578 return( 0 );
579}
580
581/*
582 * SubjectPublicKeyInfo ::= SEQUENCE {
583 * algorithm AlgorithmIdentifier,
584 * subjectPublicKey BIT STRING }
585 */
586static int x509_get_pubkey( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000587 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000588 x509_buf *pk_alg_oid,
589 mpi *N, mpi *E )
590{
Paul Bakker23986e52011-04-24 08:57:21 +0000591 int ret, can_handle;
592 size_t len;
Paul Bakker5121ce52009-01-03 21:22:43 +0000593 unsigned char *end2;
594
595 if( ( ret = x509_get_alg( p, end, pk_alg_oid ) ) != 0 )
596 return( ret );
597
598 /*
599 * only RSA public keys handled at this time
600 */
Paul Bakker400ff6f2011-02-20 10:40:16 +0000601 can_handle = 0;
602
603 if( pk_alg_oid->len == 9 &&
604 memcmp( pk_alg_oid->p, OID_PKCS1_RSA, 9 ) == 0 )
605 can_handle = 1;
606
607 if( pk_alg_oid->len == 9 &&
608 memcmp( pk_alg_oid->p, OID_PKCS1, 8 ) == 0 )
609 {
610 if( pk_alg_oid->p[8] >= 2 && pk_alg_oid->p[8] <= 5 )
611 can_handle = 1;
612
613 if ( pk_alg_oid->p[8] >= 11 && pk_alg_oid->p[8] <= 14 )
614 can_handle = 1;
615 }
616
617 if( pk_alg_oid->len == 5 &&
618 memcmp( pk_alg_oid->p, OID_RSA_SHA_OBS, 5 ) == 0 )
619 can_handle = 1;
620
621 if( can_handle == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000622 return( POLARSSL_ERR_X509_CERT_UNKNOWN_PK_ALG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000623
624 if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000625 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000626
627 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000628 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY |
629 POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000630
631 end2 = *p + len;
632
633 if( *(*p)++ != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000634 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY );
Paul Bakker5121ce52009-01-03 21:22:43 +0000635
636 /*
637 * RSAPublicKey ::= SEQUENCE {
638 * modulus INTEGER, -- n
639 * publicExponent INTEGER -- e
640 * }
641 */
642 if( ( ret = asn1_get_tag( p, end2, &len,
643 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000644 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000645
646 if( *p + len != end2 )
Paul Bakker40e46942009-01-03 21:51:57 +0000647 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY |
648 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000649
650 if( ( ret = asn1_get_mpi( p, end2, N ) ) != 0 ||
651 ( ret = asn1_get_mpi( p, end2, E ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000652 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000653
654 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000655 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY |
656 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000657
658 return( 0 );
659}
660
661static int x509_get_sig( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000662 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000663 x509_buf *sig )
664{
Paul Bakker23986e52011-04-24 08:57:21 +0000665 int ret;
666 size_t len;
Paul Bakker5121ce52009-01-03 21:22:43 +0000667
668 sig->tag = **p;
669
670 if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000671 return( POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000672
Paul Bakker74111d32011-01-15 16:57:55 +0000673
Paul Bakker5121ce52009-01-03 21:22:43 +0000674 if( --len < 1 || *(*p)++ != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000675 return( POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000676
677 sig->len = len;
678 sig->p = *p;
679
680 *p += len;
681
682 return( 0 );
683}
684
685/*
686 * X.509 v2/v3 unique identifier (not parsed)
687 */
688static int x509_get_uid( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000689 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000690 x509_buf *uid, int n )
691{
692 int ret;
693
694 if( *p == end )
695 return( 0 );
696
697 uid->tag = **p;
698
699 if( ( ret = asn1_get_tag( p, end, &uid->len,
700 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | n ) ) != 0 )
701 {
Paul Bakker40e46942009-01-03 21:51:57 +0000702 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker5121ce52009-01-03 21:22:43 +0000703 return( 0 );
704
705 return( ret );
706 }
707
708 uid->p = *p;
709 *p += uid->len;
710
711 return( 0 );
712}
713
714/*
Paul Bakkerd98030e2009-05-02 15:13:40 +0000715 * X.509 Extensions (No parsing of extensions, pointer should
716 * be either manually updated or extensions should be parsed!
Paul Bakker5121ce52009-01-03 21:22:43 +0000717 */
718static int x509_get_ext( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000719 const unsigned char *end,
Paul Bakkerd98030e2009-05-02 15:13:40 +0000720 x509_buf *ext )
Paul Bakker5121ce52009-01-03 21:22:43 +0000721{
Paul Bakker23986e52011-04-24 08:57:21 +0000722 int ret;
723 size_t len;
Paul Bakker5121ce52009-01-03 21:22:43 +0000724
725 if( *p == end )
726 return( 0 );
727
728 ext->tag = **p;
Paul Bakkerff60ee62010-03-16 21:09:09 +0000729
Paul Bakker5121ce52009-01-03 21:22:43 +0000730 if( ( ret = asn1_get_tag( p, end, &ext->len,
731 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000732 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000733
734 ext->p = *p;
735 end = *p + ext->len;
736
737 /*
738 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
739 *
740 * Extension ::= SEQUENCE {
741 * extnID OBJECT IDENTIFIER,
742 * critical BOOLEAN DEFAULT FALSE,
743 * extnValue OCTET STRING }
744 */
745 if( ( ret = asn1_get_tag( p, end, &len,
746 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000747 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000748
749 if( end != *p + len )
Paul Bakker40e46942009-01-03 21:51:57 +0000750 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
751 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000752
Paul Bakkerd98030e2009-05-02 15:13:40 +0000753 return( 0 );
754}
755
756/*
757 * X.509 CRL v2 extensions (no extensions parsed yet.)
758 */
759static int x509_get_crl_ext( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000760 const unsigned char *end,
761 x509_buf *ext )
Paul Bakkerd98030e2009-05-02 15:13:40 +0000762{
Paul Bakker23986e52011-04-24 08:57:21 +0000763 int ret;
764 size_t len;
Paul Bakkerd98030e2009-05-02 15:13:40 +0000765
766 if( ( ret = x509_get_ext( p, end, ext ) ) != 0 )
767 {
768 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
769 return( 0 );
770
771 return( ret );
772 }
773
774 while( *p < end )
775 {
776 if( ( ret = asn1_get_tag( p, end, &len,
777 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
778 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
779
780 *p += len;
781 }
782
783 if( *p != end )
784 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
785 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
786
787 return( 0 );
788}
789
Paul Bakker74111d32011-01-15 16:57:55 +0000790static int x509_get_basic_constraints( unsigned char **p,
791 const unsigned char *end,
Paul Bakker74111d32011-01-15 16:57:55 +0000792 int *ca_istrue,
793 int *max_pathlen )
794{
Paul Bakker23986e52011-04-24 08:57:21 +0000795 int ret;
796 size_t len;
Paul Bakker74111d32011-01-15 16:57:55 +0000797
798 /*
799 * BasicConstraints ::= SEQUENCE {
800 * cA BOOLEAN DEFAULT FALSE,
801 * pathLenConstraint INTEGER (0..MAX) OPTIONAL }
802 */
Paul Bakker3cccddb2011-01-16 21:46:31 +0000803 *ca_istrue = 0; /* DEFAULT FALSE */
Paul Bakker74111d32011-01-15 16:57:55 +0000804 *max_pathlen = 0; /* endless */
805
806 if( ( ret = asn1_get_tag( p, end, &len,
807 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
808 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
809
810 if( *p == end )
811 return 0;
812
Paul Bakker3cccddb2011-01-16 21:46:31 +0000813 if( ( ret = asn1_get_bool( p, end, ca_istrue ) ) != 0 )
Paul Bakker74111d32011-01-15 16:57:55 +0000814 {
815 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker3cccddb2011-01-16 21:46:31 +0000816 ret = asn1_get_int( p, end, ca_istrue );
Paul Bakker74111d32011-01-15 16:57:55 +0000817
818 if( ret != 0 )
819 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
820
Paul Bakker3cccddb2011-01-16 21:46:31 +0000821 if( *ca_istrue != 0 )
822 *ca_istrue = 1;
Paul Bakker74111d32011-01-15 16:57:55 +0000823 }
824
825 if( *p == end )
826 return 0;
827
828 if( ( ret = asn1_get_int( p, end, max_pathlen ) ) != 0 )
829 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
830
831 if( *p != end )
832 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
833 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
834
835 (*max_pathlen)++;
836
Paul Bakker74111d32011-01-15 16:57:55 +0000837 return 0;
838}
839
840static int x509_get_ns_cert_type( unsigned char **p,
841 const unsigned char *end,
842 unsigned char *ns_cert_type)
843{
844 int ret;
Paul Bakkerd61e7d92011-01-18 16:17:47 +0000845 x509_bitstring bs = { 0, 0, NULL };
Paul Bakker74111d32011-01-15 16:57:55 +0000846
847 if( ( ret = asn1_get_bitstring( p, end, &bs ) ) != 0 )
848 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
849
850 if( bs.len != 1 )
851 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
852 POLARSSL_ERR_ASN1_INVALID_LENGTH );
853
854 /* Get actual bitstring */
855 *ns_cert_type = *bs.p;
856 return 0;
857}
858
859static int x509_get_key_usage( unsigned char **p,
860 const unsigned char *end,
861 unsigned char *key_usage)
862{
863 int ret;
Paul Bakkerd61e7d92011-01-18 16:17:47 +0000864 x509_bitstring bs = { 0, 0, NULL };
Paul Bakker74111d32011-01-15 16:57:55 +0000865
866 if( ( ret = asn1_get_bitstring( p, end, &bs ) ) != 0 )
867 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
868
869 if( bs.len != 1 )
870 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
871 POLARSSL_ERR_ASN1_INVALID_LENGTH );
872
873 /* Get actual bitstring */
874 *key_usage = *bs.p;
875 return 0;
876}
877
Paul Bakkerd98030e2009-05-02 15:13:40 +0000878/*
Paul Bakker74111d32011-01-15 16:57:55 +0000879 * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
880 *
881 * KeyPurposeId ::= OBJECT IDENTIFIER
882 */
883static int x509_get_ext_key_usage( unsigned char **p,
884 const unsigned char *end,
885 x509_sequence *ext_key_usage)
886{
887 int ret;
888
889 if( ( ret = asn1_get_sequence_of( p, end, ext_key_usage, ASN1_OID ) ) != 0 )
890 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
891
892 /* Sequence length must be >= 1 */
893 if( ext_key_usage->buf.p == NULL )
894 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
895 POLARSSL_ERR_ASN1_INVALID_LENGTH );
896
897 return 0;
898}
899
900/*
901 * X.509 v3 extensions
902 *
903 * TODO: Perform all of the basic constraints tests required by the RFC
904 * TODO: Set values for undetected extensions to a sane default?
905 *
Paul Bakkerd98030e2009-05-02 15:13:40 +0000906 */
907static int x509_get_crt_ext( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000908 const unsigned char *end,
Paul Bakker74111d32011-01-15 16:57:55 +0000909 x509_cert *crt )
Paul Bakkerd98030e2009-05-02 15:13:40 +0000910{
Paul Bakker23986e52011-04-24 08:57:21 +0000911 int ret;
912 size_t len;
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000913 unsigned char *end_ext_data, *end_ext_octet;
Paul Bakkerd98030e2009-05-02 15:13:40 +0000914
Paul Bakker74111d32011-01-15 16:57:55 +0000915 if( ( ret = x509_get_ext( p, end, &crt->v3_ext ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +0000916 {
917 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
918 return( 0 );
919
920 return( ret );
921 }
922
Paul Bakker5121ce52009-01-03 21:22:43 +0000923 while( *p < end )
924 {
Paul Bakker74111d32011-01-15 16:57:55 +0000925 /*
926 * Extension ::= SEQUENCE {
927 * extnID OBJECT IDENTIFIER,
928 * critical BOOLEAN DEFAULT FALSE,
929 * extnValue OCTET STRING }
930 */
931 x509_buf extn_oid = {0, 0, NULL};
932 int is_critical = 0; /* DEFAULT FALSE */
933
Paul Bakker5121ce52009-01-03 21:22:43 +0000934 if( ( ret = asn1_get_tag( p, end, &len,
935 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000936 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000937
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000938 end_ext_data = *p + len;
939
Paul Bakker74111d32011-01-15 16:57:55 +0000940 /* Get extension ID */
941 extn_oid.tag = **p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000942
Paul Bakker74111d32011-01-15 16:57:55 +0000943 if( ( ret = asn1_get_tag( p, end, &extn_oid.len, ASN1_OID ) ) != 0 )
944 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000945
Paul Bakker74111d32011-01-15 16:57:55 +0000946 extn_oid.p = *p;
947 *p += extn_oid.len;
948
949 if( ( end - *p ) < 1 )
950 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
951 POLARSSL_ERR_ASN1_OUT_OF_DATA );
952
953 /* Get optional critical */
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000954 if( ( ret = asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 &&
Paul Bakker40e46942009-01-03 21:51:57 +0000955 ( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) )
956 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000957
Paul Bakker74111d32011-01-15 16:57:55 +0000958 /* Data should be octet string type */
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000959 if( ( ret = asn1_get_tag( p, end_ext_data, &len,
Paul Bakker5121ce52009-01-03 21:22:43 +0000960 ASN1_OCTET_STRING ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000961 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000962
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000963 end_ext_octet = *p + len;
Paul Bakkerff60ee62010-03-16 21:09:09 +0000964
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000965 if( end_ext_octet != end_ext_data )
966 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
967 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000968
Paul Bakker74111d32011-01-15 16:57:55 +0000969 /*
970 * Detect supported extensions
971 */
972 if( ( OID_SIZE( OID_BASIC_CONSTRAINTS ) == extn_oid.len ) &&
973 memcmp( extn_oid.p, OID_BASIC_CONSTRAINTS, extn_oid.len ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000974 {
Paul Bakker74111d32011-01-15 16:57:55 +0000975 /* Parse basic constraints */
976 if( ( ret = x509_get_basic_constraints( p, end_ext_octet,
Paul Bakker3cccddb2011-01-16 21:46:31 +0000977 &crt->ca_istrue, &crt->max_pathlen ) ) != 0 )
Paul Bakker74111d32011-01-15 16:57:55 +0000978 return ( ret );
979 crt->ext_types |= EXT_BASIC_CONSTRAINTS;
Paul Bakker5121ce52009-01-03 21:22:43 +0000980 }
Paul Bakker74111d32011-01-15 16:57:55 +0000981 else if( ( OID_SIZE( OID_NS_CERT_TYPE ) == extn_oid.len ) &&
982 memcmp( extn_oid.p, OID_NS_CERT_TYPE, extn_oid.len ) == 0 )
983 {
984 /* Parse netscape certificate type */
985 if( ( ret = x509_get_ns_cert_type( p, end_ext_octet,
986 &crt->ns_cert_type ) ) != 0 )
987 return ( ret );
988 crt->ext_types |= EXT_NS_CERT_TYPE;
989 }
990 else if( ( OID_SIZE( OID_KEY_USAGE ) == extn_oid.len ) &&
991 memcmp( extn_oid.p, OID_KEY_USAGE, extn_oid.len ) == 0 )
992 {
993 /* Parse key usage */
994 if( ( ret = x509_get_key_usage( p, end_ext_octet,
995 &crt->key_usage ) ) != 0 )
996 return ( ret );
997 crt->ext_types |= EXT_KEY_USAGE;
998 }
999 else if( ( OID_SIZE( OID_EXTENDED_KEY_USAGE ) == extn_oid.len ) &&
1000 memcmp( extn_oid.p, OID_EXTENDED_KEY_USAGE, extn_oid.len ) == 0 )
1001 {
1002 /* Parse extended key usage */
1003 if( ( ret = x509_get_ext_key_usage( p, end_ext_octet,
1004 &crt->ext_key_usage ) ) != 0 )
1005 return ( ret );
1006 crt->ext_types |= EXT_EXTENDED_KEY_USAGE;
1007 }
1008 else
1009 {
1010 /* No parser found, skip extension */
1011 *p = end_ext_octet;
Paul Bakker5121ce52009-01-03 21:22:43 +00001012
Paul Bakker74111d32011-01-15 16:57:55 +00001013 if( is_critical )
1014 {
1015 /* Data is marked as critical: fail */
1016 return ( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
1017 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
1018 }
1019 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001020 }
1021
1022 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +00001023 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
1024 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001025
Paul Bakker5121ce52009-01-03 21:22:43 +00001026 return( 0 );
1027}
1028
1029/*
Paul Bakkerd98030e2009-05-02 15:13:40 +00001030 * X.509 CRL Entries
1031 */
1032static int x509_get_entries( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +00001033 const unsigned char *end,
Paul Bakkerd98030e2009-05-02 15:13:40 +00001034 x509_crl_entry *entry )
1035{
Paul Bakker23986e52011-04-24 08:57:21 +00001036 int ret;
1037 size_t entry_len;
Paul Bakkerd98030e2009-05-02 15:13:40 +00001038 x509_crl_entry *cur_entry = entry;
1039
1040 if( *p == end )
1041 return( 0 );
1042
Paul Bakker9be19372009-07-27 20:21:53 +00001043 if( ( ret = asn1_get_tag( p, end, &entry_len,
Paul Bakkerd98030e2009-05-02 15:13:40 +00001044 ASN1_SEQUENCE | ASN1_CONSTRUCTED ) ) != 0 )
1045 {
1046 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
1047 return( 0 );
1048
1049 return( ret );
1050 }
1051
Paul Bakker9be19372009-07-27 20:21:53 +00001052 end = *p + entry_len;
Paul Bakkerd98030e2009-05-02 15:13:40 +00001053
1054 while( *p < end )
1055 {
Paul Bakker23986e52011-04-24 08:57:21 +00001056 size_t len2;
Paul Bakkerd98030e2009-05-02 15:13:40 +00001057
1058 if( ( ret = asn1_get_tag( p, end, &len2,
1059 ASN1_SEQUENCE | ASN1_CONSTRUCTED ) ) != 0 )
1060 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00001061 return( ret );
1062 }
1063
Paul Bakker9be19372009-07-27 20:21:53 +00001064 cur_entry->raw.tag = **p;
1065 cur_entry->raw.p = *p;
1066 cur_entry->raw.len = len2;
1067
Paul Bakkerd98030e2009-05-02 15:13:40 +00001068 if( ( ret = x509_get_serial( p, end, &cur_entry->serial ) ) != 0 )
1069 return( ret );
1070
Paul Bakker91200182010-02-18 21:26:15 +00001071 if( ( ret = x509_get_time( p, end, &cur_entry->revocation_date ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +00001072 return( ret );
1073
1074 if( ( ret = x509_get_crl_ext( p, end, &cur_entry->entry_ext ) ) != 0 )
1075 return( ret );
1076
Paul Bakker74111d32011-01-15 16:57:55 +00001077 if ( *p < end )
1078 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00001079 cur_entry->next = malloc( sizeof( x509_crl_entry ) );
1080 cur_entry = cur_entry->next;
1081 memset( cur_entry, 0, sizeof( x509_crl_entry ) );
1082 }
1083 }
1084
1085 return( 0 );
1086}
1087
Paul Bakker27d66162010-03-17 06:56:01 +00001088static int x509_get_sig_alg( const x509_buf *sig_oid, int *sig_alg )
1089{
1090 if( sig_oid->len == 9 &&
1091 memcmp( sig_oid->p, OID_PKCS1, 8 ) == 0 )
1092 {
1093 if( sig_oid->p[8] >= 2 && sig_oid->p[8] <= 5 )
1094 {
1095 *sig_alg = sig_oid->p[8];
1096 return( 0 );
1097 }
1098
1099 if ( sig_oid->p[8] >= 11 && sig_oid->p[8] <= 14 )
1100 {
1101 *sig_alg = sig_oid->p[8];
1102 return( 0 );
1103 }
1104
1105 return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
1106 }
Paul Bakker400ff6f2011-02-20 10:40:16 +00001107 if( sig_oid->len == 5 &&
1108 memcmp( sig_oid->p, OID_RSA_SHA_OBS, 5 ) == 0 )
1109 {
1110 *sig_alg = SIG_RSA_SHA1;
1111 return( 0 );
1112 }
Paul Bakker27d66162010-03-17 06:56:01 +00001113
1114 return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
1115}
1116
Paul Bakkerd98030e2009-05-02 15:13:40 +00001117/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001118 * Parse one or more certificates and add them to the chained list
1119 */
Paul Bakker23986e52011-04-24 08:57:21 +00001120int x509parse_crt( x509_cert *chain, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +00001121{
Paul Bakker23986e52011-04-24 08:57:21 +00001122 int ret;
1123 size_t len, use_len;
Paul Bakker5121ce52009-01-03 21:22:43 +00001124 unsigned char *p, *end;
1125 x509_cert *crt;
Paul Bakker96743fc2011-02-12 14:30:57 +00001126#if defined(POLARSSL_PEM_C)
1127 pem_context pem;
1128#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00001129
1130 crt = chain;
1131
Paul Bakker320a4b52009-03-28 18:52:39 +00001132 /*
1133 * Check for valid input
1134 */
1135 if( crt == NULL || buf == NULL )
1136 return( 1 );
1137
Paul Bakkere9581d62009-03-28 20:29:25 +00001138 while( crt->version != 0 && crt->next != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +00001139 crt = crt->next;
1140
1141 /*
Paul Bakker320a4b52009-03-28 18:52:39 +00001142 * Add new certificate on the end of the chain if needed.
1143 */
Paul Bakkere9581d62009-03-28 20:29:25 +00001144 if ( crt->version != 0 && crt->next == NULL)
Paul Bakker320a4b52009-03-28 18:52:39 +00001145 {
1146 crt->next = (x509_cert *) malloc( sizeof( x509_cert ) );
1147
Paul Bakker7d06ad22009-05-02 15:53:56 +00001148 if( crt->next == NULL )
1149 {
Paul Bakker320a4b52009-03-28 18:52:39 +00001150 x509_free( crt );
Paul Bakker7d06ad22009-05-02 15:53:56 +00001151 return( 1 );
1152 }
Paul Bakker320a4b52009-03-28 18:52:39 +00001153
Paul Bakker7d06ad22009-05-02 15:53:56 +00001154 crt = crt->next;
1155 memset( crt, 0, sizeof( x509_cert ) );
Paul Bakker320a4b52009-03-28 18:52:39 +00001156 }
1157
Paul Bakker96743fc2011-02-12 14:30:57 +00001158#if defined(POLARSSL_PEM_C)
1159 pem_init( &pem );
1160 ret = pem_read_buffer( &pem,
1161 "-----BEGIN CERTIFICATE-----",
1162 "-----END CERTIFICATE-----",
1163 buf, NULL, 0, &use_len );
Paul Bakker5121ce52009-01-03 21:22:43 +00001164
Paul Bakker96743fc2011-02-12 14:30:57 +00001165 if( ret == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001166 {
Paul Bakker96743fc2011-02-12 14:30:57 +00001167 /*
1168 * Was PEM encoded
1169 */
1170 buflen -= use_len;
1171 buf += use_len;
Paul Bakker5121ce52009-01-03 21:22:43 +00001172
1173 /*
Paul Bakker96743fc2011-02-12 14:30:57 +00001174 * Steal PEM buffer
Paul Bakker5121ce52009-01-03 21:22:43 +00001175 */
Paul Bakker96743fc2011-02-12 14:30:57 +00001176 p = pem.buf;
1177 pem.buf = NULL;
1178 len = pem.buflen;
1179 pem_free( &pem );
1180 }
1181 else if( ret != POLARSSL_ERR_PEM_NO_HEADER_PRESENT )
1182 {
1183 pem_free( &pem );
1184 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001185 }
1186 else
1187 {
1188 /*
1189 * nope, copy the raw DER data
1190 */
1191 p = (unsigned char *) malloc( len = buflen );
1192
1193 if( p == NULL )
1194 return( 1 );
1195
1196 memcpy( p, buf, buflen );
1197
1198 buflen = 0;
1199 }
Paul Bakker96743fc2011-02-12 14:30:57 +00001200#else
1201 p = (unsigned char *) malloc( len = buflen );
1202
1203 if( p == NULL )
1204 return( 1 );
1205
1206 memcpy( p, buf, buflen );
1207
1208 buflen = 0;
1209#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00001210
1211 crt->raw.p = p;
1212 crt->raw.len = len;
1213 end = p + len;
1214
1215 /*
1216 * Certificate ::= SEQUENCE {
1217 * tbsCertificate TBSCertificate,
1218 * signatureAlgorithm AlgorithmIdentifier,
1219 * signatureValue BIT STRING }
1220 */
1221 if( ( ret = asn1_get_tag( &p, end, &len,
1222 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1223 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001224 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +00001225 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT );
Paul Bakker5121ce52009-01-03 21:22:43 +00001226 }
1227
Paul Bakker23986e52011-04-24 08:57:21 +00001228 if( len != (size_t) ( end - p ) )
Paul Bakker5121ce52009-01-03 21:22:43 +00001229 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001230 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +00001231 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT |
1232 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001233 }
1234
1235 /*
1236 * TBSCertificate ::= SEQUENCE {
1237 */
1238 crt->tbs.p = p;
1239
1240 if( ( ret = asn1_get_tag( &p, end, &len,
1241 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1242 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001243 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +00001244 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001245 }
1246
1247 end = p + len;
1248 crt->tbs.len = end - crt->tbs.p;
1249
1250 /*
1251 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
1252 *
1253 * CertificateSerialNumber ::= INTEGER
1254 *
1255 * signature AlgorithmIdentifier
1256 */
1257 if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 ||
1258 ( ret = x509_get_serial( &p, end, &crt->serial ) ) != 0 ||
1259 ( ret = x509_get_alg( &p, end, &crt->sig_oid1 ) ) != 0 )
1260 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001261 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001262 return( ret );
1263 }
1264
1265 crt->version++;
1266
1267 if( crt->version > 3 )
1268 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001269 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +00001270 return( POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION );
Paul Bakker5121ce52009-01-03 21:22:43 +00001271 }
1272
Paul Bakker27d66162010-03-17 06:56:01 +00001273 if( ( ret = x509_get_sig_alg( &crt->sig_oid1, &crt->sig_alg ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001274 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001275 x509_free( crt );
Paul Bakker27d66162010-03-17 06:56:01 +00001276 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001277 }
1278
1279 /*
1280 * issuer Name
1281 */
1282 crt->issuer_raw.p = p;
1283
1284 if( ( ret = asn1_get_tag( &p, end, &len,
1285 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1286 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001287 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +00001288 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001289 }
1290
1291 if( ( ret = x509_get_name( &p, p + len, &crt->issuer ) ) != 0 )
1292 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001293 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001294 return( ret );
1295 }
1296
1297 crt->issuer_raw.len = p - crt->issuer_raw.p;
1298
1299 /*
1300 * Validity ::= SEQUENCE {
1301 * notBefore Time,
1302 * notAfter Time }
1303 *
1304 */
1305 if( ( ret = x509_get_dates( &p, end, &crt->valid_from,
1306 &crt->valid_to ) ) != 0 )
1307 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001308 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001309 return( ret );
1310 }
1311
1312 /*
1313 * subject Name
1314 */
1315 crt->subject_raw.p = p;
1316
1317 if( ( ret = asn1_get_tag( &p, end, &len,
1318 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1319 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001320 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +00001321 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001322 }
1323
1324 if( ( ret = x509_get_name( &p, p + len, &crt->subject ) ) != 0 )
1325 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001326 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001327 return( ret );
1328 }
1329
1330 crt->subject_raw.len = p - crt->subject_raw.p;
1331
1332 /*
1333 * SubjectPublicKeyInfo ::= SEQUENCE
1334 * algorithm AlgorithmIdentifier,
1335 * subjectPublicKey BIT STRING }
1336 */
1337 if( ( ret = asn1_get_tag( &p, end, &len,
1338 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1339 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001340 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +00001341 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001342 }
1343
1344 if( ( ret = x509_get_pubkey( &p, p + len, &crt->pk_oid,
1345 &crt->rsa.N, &crt->rsa.E ) ) != 0 )
1346 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001347 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001348 return( ret );
1349 }
1350
1351 if( ( ret = rsa_check_pubkey( &crt->rsa ) ) != 0 )
1352 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001353 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001354 return( ret );
1355 }
1356
1357 crt->rsa.len = mpi_size( &crt->rsa.N );
1358
1359 /*
1360 * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
1361 * -- If present, version shall be v2 or v3
1362 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
1363 * -- If present, version shall be v2 or v3
1364 * extensions [3] EXPLICIT Extensions OPTIONAL
1365 * -- If present, version shall be v3
1366 */
1367 if( crt->version == 2 || crt->version == 3 )
1368 {
1369 ret = x509_get_uid( &p, end, &crt->issuer_id, 1 );
1370 if( ret != 0 )
1371 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001372 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001373 return( ret );
1374 }
1375 }
1376
1377 if( crt->version == 2 || crt->version == 3 )
1378 {
1379 ret = x509_get_uid( &p, end, &crt->subject_id, 2 );
1380 if( ret != 0 )
1381 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001382 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001383 return( ret );
1384 }
1385 }
1386
1387 if( crt->version == 3 )
1388 {
Paul Bakker74111d32011-01-15 16:57:55 +00001389 ret = x509_get_crt_ext( &p, end, crt);
Paul Bakker5121ce52009-01-03 21:22:43 +00001390 if( ret != 0 )
1391 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001392 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001393 return( ret );
1394 }
1395 }
1396
1397 if( p != end )
1398 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001399 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +00001400 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT |
1401 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001402 }
1403
1404 end = crt->raw.p + crt->raw.len;
1405
1406 /*
1407 * signatureAlgorithm AlgorithmIdentifier,
1408 * signatureValue BIT STRING
1409 */
1410 if( ( ret = x509_get_alg( &p, end, &crt->sig_oid2 ) ) != 0 )
1411 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001412 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001413 return( ret );
1414 }
1415
Paul Bakker320a4b52009-03-28 18:52:39 +00001416 if( memcmp( crt->sig_oid1.p, crt->sig_oid2.p, crt->sig_oid1.len ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001417 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001418 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +00001419 return( POLARSSL_ERR_X509_CERT_SIG_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001420 }
1421
1422 if( ( ret = x509_get_sig( &p, end, &crt->sig ) ) != 0 )
1423 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001424 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001425 return( ret );
1426 }
1427
1428 if( p != end )
1429 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001430 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +00001431 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT |
1432 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001433 }
1434
Paul Bakker5121ce52009-01-03 21:22:43 +00001435 if( buflen > 0 )
Paul Bakker320a4b52009-03-28 18:52:39 +00001436 {
1437 crt->next = (x509_cert *) malloc( sizeof( x509_cert ) );
1438
Paul Bakker7d06ad22009-05-02 15:53:56 +00001439 if( crt->next == NULL )
1440 {
Paul Bakker320a4b52009-03-28 18:52:39 +00001441 x509_free( crt );
Paul Bakker7d06ad22009-05-02 15:53:56 +00001442 return( 1 );
1443 }
Paul Bakker320a4b52009-03-28 18:52:39 +00001444
Paul Bakker7d06ad22009-05-02 15:53:56 +00001445 crt = crt->next;
1446 memset( crt, 0, sizeof( x509_cert ) );
Paul Bakker320a4b52009-03-28 18:52:39 +00001447
Paul Bakker5121ce52009-01-03 21:22:43 +00001448 return( x509parse_crt( crt, buf, buflen ) );
Paul Bakker320a4b52009-03-28 18:52:39 +00001449 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001450
1451 return( 0 );
1452}
1453
1454/*
Paul Bakkerd98030e2009-05-02 15:13:40 +00001455 * Parse one or more CRLs and add them to the chained list
1456 */
Paul Bakker23986e52011-04-24 08:57:21 +00001457int x509parse_crl( x509_crl *chain, const unsigned char *buf, size_t buflen )
Paul Bakkerd98030e2009-05-02 15:13:40 +00001458{
Paul Bakker23986e52011-04-24 08:57:21 +00001459 int ret;
1460 size_t len, use_len;
Paul Bakkerd98030e2009-05-02 15:13:40 +00001461 unsigned char *p, *end;
1462 x509_crl *crl;
Paul Bakker96743fc2011-02-12 14:30:57 +00001463#if defined(POLARSSL_PEM_C)
1464 pem_context pem;
1465#endif
Paul Bakkerd98030e2009-05-02 15:13:40 +00001466
1467 crl = chain;
1468
1469 /*
1470 * Check for valid input
1471 */
1472 if( crl == NULL || buf == NULL )
1473 return( 1 );
1474
1475 while( crl->version != 0 && crl->next != NULL )
1476 crl = crl->next;
1477
1478 /*
1479 * Add new CRL on the end of the chain if needed.
1480 */
1481 if ( crl->version != 0 && crl->next == NULL)
1482 {
1483 crl->next = (x509_crl *) malloc( sizeof( x509_crl ) );
1484
Paul Bakker7d06ad22009-05-02 15:53:56 +00001485 if( crl->next == NULL )
1486 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00001487 x509_crl_free( crl );
Paul Bakker7d06ad22009-05-02 15:53:56 +00001488 return( 1 );
1489 }
Paul Bakkerd98030e2009-05-02 15:13:40 +00001490
Paul Bakker7d06ad22009-05-02 15:53:56 +00001491 crl = crl->next;
1492 memset( crl, 0, sizeof( x509_crl ) );
Paul Bakkerd98030e2009-05-02 15:13:40 +00001493 }
1494
Paul Bakker96743fc2011-02-12 14:30:57 +00001495#if defined(POLARSSL_PEM_C)
1496 pem_init( &pem );
1497 ret = pem_read_buffer( &pem,
1498 "-----BEGIN X509 CRL-----",
1499 "-----END X509 CRL-----",
1500 buf, NULL, 0, &use_len );
Paul Bakkerd98030e2009-05-02 15:13:40 +00001501
Paul Bakker96743fc2011-02-12 14:30:57 +00001502 if( ret == 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +00001503 {
Paul Bakker96743fc2011-02-12 14:30:57 +00001504 /*
1505 * Was PEM encoded
1506 */
1507 buflen -= use_len;
1508 buf += use_len;
Paul Bakkerd98030e2009-05-02 15:13:40 +00001509
1510 /*
Paul Bakker96743fc2011-02-12 14:30:57 +00001511 * Steal PEM buffer
Paul Bakkerd98030e2009-05-02 15:13:40 +00001512 */
Paul Bakker96743fc2011-02-12 14:30:57 +00001513 p = pem.buf;
1514 pem.buf = NULL;
1515 len = pem.buflen;
1516 pem_free( &pem );
1517 }
1518 else if( ret != POLARSSL_ERR_PEM_NO_HEADER_PRESENT )
1519 {
1520 pem_free( &pem );
1521 return( ret );
Paul Bakkerd98030e2009-05-02 15:13:40 +00001522 }
1523 else
1524 {
1525 /*
1526 * nope, copy the raw DER data
1527 */
1528 p = (unsigned char *) malloc( len = buflen );
1529
1530 if( p == NULL )
1531 return( 1 );
1532
1533 memcpy( p, buf, buflen );
1534
1535 buflen = 0;
1536 }
Paul Bakker96743fc2011-02-12 14:30:57 +00001537#else
1538 p = (unsigned char *) malloc( len = buflen );
1539
1540 if( p == NULL )
1541 return( 1 );
1542
1543 memcpy( p, buf, buflen );
1544
1545 buflen = 0;
1546#endif
Paul Bakkerd98030e2009-05-02 15:13:40 +00001547
1548 crl->raw.p = p;
1549 crl->raw.len = len;
1550 end = p + len;
1551
1552 /*
1553 * CertificateList ::= SEQUENCE {
1554 * tbsCertList TBSCertList,
1555 * signatureAlgorithm AlgorithmIdentifier,
1556 * signatureValue BIT STRING }
1557 */
1558 if( ( ret = asn1_get_tag( &p, end, &len,
1559 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1560 {
1561 x509_crl_free( crl );
1562 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT );
1563 }
1564
Paul Bakker23986e52011-04-24 08:57:21 +00001565 if( len != (size_t) ( end - p ) )
Paul Bakkerd98030e2009-05-02 15:13:40 +00001566 {
1567 x509_crl_free( crl );
1568 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT |
1569 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
1570 }
1571
1572 /*
1573 * TBSCertList ::= SEQUENCE {
1574 */
1575 crl->tbs.p = p;
1576
1577 if( ( ret = asn1_get_tag( &p, end, &len,
1578 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1579 {
1580 x509_crl_free( crl );
1581 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
1582 }
1583
1584 end = p + len;
1585 crl->tbs.len = end - crl->tbs.p;
1586
1587 /*
1588 * Version ::= INTEGER OPTIONAL { v1(0), v2(1) }
1589 * -- if present, MUST be v2
1590 *
1591 * signature AlgorithmIdentifier
1592 */
1593 if( ( ret = x509_get_version( &p, end, &crl->version ) ) != 0 ||
1594 ( ret = x509_get_alg( &p, end, &crl->sig_oid1 ) ) != 0 )
1595 {
1596 x509_crl_free( crl );
1597 return( ret );
1598 }
1599
1600 crl->version++;
1601
1602 if( crl->version > 2 )
1603 {
1604 x509_crl_free( crl );
1605 return( POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION );
1606 }
1607
Paul Bakker27d66162010-03-17 06:56:01 +00001608 if( ( ret = x509_get_sig_alg( &crl->sig_oid1, &crl->sig_alg ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +00001609 {
1610 x509_crl_free( crl );
1611 return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
1612 }
1613
1614 /*
1615 * issuer Name
1616 */
1617 crl->issuer_raw.p = p;
1618
1619 if( ( ret = asn1_get_tag( &p, end, &len,
1620 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1621 {
1622 x509_crl_free( crl );
1623 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
1624 }
1625
1626 if( ( ret = x509_get_name( &p, p + len, &crl->issuer ) ) != 0 )
1627 {
1628 x509_crl_free( crl );
1629 return( ret );
1630 }
1631
1632 crl->issuer_raw.len = p - crl->issuer_raw.p;
1633
1634 /*
1635 * thisUpdate Time
1636 * nextUpdate Time OPTIONAL
1637 */
Paul Bakker91200182010-02-18 21:26:15 +00001638 if( ( ret = x509_get_time( &p, end, &crl->this_update ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +00001639 {
1640 x509_crl_free( crl );
1641 return( ret );
1642 }
1643
Paul Bakker91200182010-02-18 21:26:15 +00001644 if( ( ret = x509_get_time( &p, end, &crl->next_update ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +00001645 {
Paul Bakker635f4b42009-07-20 20:34:41 +00001646 if ( ret != ( POLARSSL_ERR_X509_CERT_INVALID_DATE |
Paul Bakker9be19372009-07-27 20:21:53 +00001647 POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) &&
1648 ret != ( POLARSSL_ERR_X509_CERT_INVALID_DATE |
1649 POLARSSL_ERR_ASN1_OUT_OF_DATA ) )
Paul Bakker635f4b42009-07-20 20:34:41 +00001650 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00001651 x509_crl_free( crl );
1652 return( ret );
1653 }
1654 }
1655
1656 /*
1657 * revokedCertificates SEQUENCE OF SEQUENCE {
1658 * userCertificate CertificateSerialNumber,
1659 * revocationDate Time,
1660 * crlEntryExtensions Extensions OPTIONAL
1661 * -- if present, MUST be v2
1662 * } OPTIONAL
1663 */
1664 if( ( ret = x509_get_entries( &p, end, &crl->entry ) ) != 0 )
1665 {
1666 x509_crl_free( crl );
1667 return( ret );
1668 }
1669
1670 /*
1671 * crlExtensions EXPLICIT Extensions OPTIONAL
1672 * -- if present, MUST be v2
1673 */
1674 if( crl->version == 2 )
1675 {
1676 ret = x509_get_crl_ext( &p, end, &crl->crl_ext );
1677
1678 if( ret != 0 )
1679 {
1680 x509_crl_free( crl );
1681 return( ret );
1682 }
1683 }
1684
1685 if( p != end )
1686 {
1687 x509_crl_free( crl );
1688 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT |
1689 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
1690 }
1691
1692 end = crl->raw.p + crl->raw.len;
1693
1694 /*
1695 * signatureAlgorithm AlgorithmIdentifier,
1696 * signatureValue BIT STRING
1697 */
1698 if( ( ret = x509_get_alg( &p, end, &crl->sig_oid2 ) ) != 0 )
1699 {
1700 x509_crl_free( crl );
1701 return( ret );
1702 }
1703
1704 if( memcmp( crl->sig_oid1.p, crl->sig_oid2.p, crl->sig_oid1.len ) != 0 )
1705 {
1706 x509_crl_free( crl );
1707 return( POLARSSL_ERR_X509_CERT_SIG_MISMATCH );
1708 }
1709
1710 if( ( ret = x509_get_sig( &p, end, &crl->sig ) ) != 0 )
1711 {
1712 x509_crl_free( crl );
1713 return( ret );
1714 }
1715
1716 if( p != end )
1717 {
1718 x509_crl_free( crl );
1719 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT |
1720 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
1721 }
1722
1723 if( buflen > 0 )
1724 {
1725 crl->next = (x509_crl *) malloc( sizeof( x509_crl ) );
1726
Paul Bakker7d06ad22009-05-02 15:53:56 +00001727 if( crl->next == NULL )
1728 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00001729 x509_crl_free( crl );
Paul Bakker7d06ad22009-05-02 15:53:56 +00001730 return( 1 );
1731 }
Paul Bakkerd98030e2009-05-02 15:13:40 +00001732
Paul Bakker7d06ad22009-05-02 15:53:56 +00001733 crl = crl->next;
1734 memset( crl, 0, sizeof( x509_crl ) );
Paul Bakkerd98030e2009-05-02 15:13:40 +00001735
1736 return( x509parse_crl( crl, buf, buflen ) );
1737 }
1738
1739 return( 0 );
1740}
1741
1742/*
Paul Bakker2b245eb2009-04-19 18:44:26 +00001743 * Load all data from a file into a given buffer.
1744 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001745int load_file( const char *path, unsigned char **buf, size_t *n )
Paul Bakker2b245eb2009-04-19 18:44:26 +00001746{
Paul Bakkerd98030e2009-05-02 15:13:40 +00001747 FILE *f;
Paul Bakker2b245eb2009-04-19 18:44:26 +00001748
Paul Bakkerd98030e2009-05-02 15:13:40 +00001749 if( ( f = fopen( path, "rb" ) ) == NULL )
1750 return( 1 );
Paul Bakker2b245eb2009-04-19 18:44:26 +00001751
Paul Bakkerd98030e2009-05-02 15:13:40 +00001752 fseek( f, 0, SEEK_END );
1753 *n = (size_t) ftell( f );
1754 fseek( f, 0, SEEK_SET );
Paul Bakker2b245eb2009-04-19 18:44:26 +00001755
Paul Bakkerd98030e2009-05-02 15:13:40 +00001756 if( ( *buf = (unsigned char *) malloc( *n + 1 ) ) == NULL )
1757 return( 1 );
Paul Bakker2b245eb2009-04-19 18:44:26 +00001758
Paul Bakkerd98030e2009-05-02 15:13:40 +00001759 if( fread( *buf, 1, *n, f ) != *n )
1760 {
1761 fclose( f );
1762 free( *buf );
1763 return( 1 );
1764 }
Paul Bakker2b245eb2009-04-19 18:44:26 +00001765
Paul Bakkerd98030e2009-05-02 15:13:40 +00001766 fclose( f );
Paul Bakker2b245eb2009-04-19 18:44:26 +00001767
Paul Bakkerd98030e2009-05-02 15:13:40 +00001768 (*buf)[*n] = '\0';
Paul Bakker2b245eb2009-04-19 18:44:26 +00001769
Paul Bakkerd98030e2009-05-02 15:13:40 +00001770 return( 0 );
Paul Bakker2b245eb2009-04-19 18:44:26 +00001771}
1772
1773/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001774 * Load one or more certificates and add them to the chained list
1775 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001776int x509parse_crtfile( x509_cert *chain, const char *path )
Paul Bakker5121ce52009-01-03 21:22:43 +00001777{
1778 int ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001779 size_t n;
1780 unsigned char *buf;
1781
Paul Bakker2b245eb2009-04-19 18:44:26 +00001782 if ( load_file( path, &buf, &n ) )
Paul Bakker5121ce52009-01-03 21:22:43 +00001783 return( 1 );
1784
Paul Bakker5121ce52009-01-03 21:22:43 +00001785 ret = x509parse_crt( chain, buf, (int) n );
1786
1787 memset( buf, 0, n + 1 );
1788 free( buf );
Paul Bakker5121ce52009-01-03 21:22:43 +00001789
1790 return( ret );
1791}
1792
Paul Bakkerd98030e2009-05-02 15:13:40 +00001793/*
1794 * Load one or more CRLs and add them to the chained list
1795 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001796int x509parse_crlfile( x509_crl *chain, const char *path )
Paul Bakkerd98030e2009-05-02 15:13:40 +00001797{
1798 int ret;
1799 size_t n;
1800 unsigned char *buf;
1801
1802 if ( load_file( path, &buf, &n ) )
1803 return( 1 );
1804
1805 ret = x509parse_crl( chain, buf, (int) n );
1806
1807 memset( buf, 0, n + 1 );
1808 free( buf );
1809
1810 return( ret );
1811}
1812
Paul Bakker5121ce52009-01-03 21:22:43 +00001813/*
1814 * Parse a private RSA key
1815 */
Paul Bakker23986e52011-04-24 08:57:21 +00001816int x509parse_key( rsa_context *rsa, const unsigned char *key, size_t keylen,
1817 const unsigned char *pwd, size_t pwdlen )
Paul Bakker5121ce52009-01-03 21:22:43 +00001818{
Paul Bakker23986e52011-04-24 08:57:21 +00001819 int ret;
1820 size_t len;
Paul Bakker5121ce52009-01-03 21:22:43 +00001821 unsigned char *p, *end;
Paul Bakker96743fc2011-02-12 14:30:57 +00001822#if defined(POLARSSL_PEM_C)
1823 pem_context pem;
Paul Bakker5121ce52009-01-03 21:22:43 +00001824
Paul Bakker96743fc2011-02-12 14:30:57 +00001825 pem_init( &pem );
1826 ret = pem_read_buffer( &pem,
1827 "-----BEGIN RSA PRIVATE KEY-----",
1828 "-----END RSA PRIVATE KEY-----",
1829 key, pwd, pwdlen, &len );
Paul Bakker5121ce52009-01-03 21:22:43 +00001830
Paul Bakker96743fc2011-02-12 14:30:57 +00001831 if( ret == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001832 {
Paul Bakker96743fc2011-02-12 14:30:57 +00001833 /*
1834 * Was PEM encoded
1835 */
1836 keylen = pem.buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +00001837 }
Paul Bakker96743fc2011-02-12 14:30:57 +00001838 else if( ret != POLARSSL_ERR_PEM_NO_HEADER_PRESENT )
Paul Bakkerff60ee62010-03-16 21:09:09 +00001839 {
Paul Bakker96743fc2011-02-12 14:30:57 +00001840 pem_free( &pem );
1841 return( ret );
Paul Bakkerff60ee62010-03-16 21:09:09 +00001842 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001843
Paul Bakker96743fc2011-02-12 14:30:57 +00001844 p = ( ret == 0 ) ? pem.buf : (unsigned char *) key;
1845#else
1846 p = (unsigned char *) key;
1847#endif
1848 end = p + keylen;
1849
Paul Bakker5121ce52009-01-03 21:22:43 +00001850 /*
1851 * RSAPrivateKey ::= SEQUENCE {
1852 * version Version,
1853 * modulus INTEGER, -- n
1854 * publicExponent INTEGER, -- e
1855 * privateExponent INTEGER, -- d
1856 * prime1 INTEGER, -- p
1857 * prime2 INTEGER, -- q
1858 * exponent1 INTEGER, -- d mod (p-1)
1859 * exponent2 INTEGER, -- d mod (q-1)
1860 * coefficient INTEGER, -- (inverse of q) mod p
1861 * otherPrimeInfos OtherPrimeInfos OPTIONAL
1862 * }
1863 */
1864 if( ( ret = asn1_get_tag( &p, end, &len,
1865 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1866 {
Paul Bakker96743fc2011-02-12 14:30:57 +00001867#if defined(POLARSSL_PEM_C)
1868 pem_free( &pem );
1869#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00001870 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001871 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001872 }
1873
1874 end = p + len;
1875
1876 if( ( ret = asn1_get_int( &p, end, &rsa->ver ) ) != 0 )
1877 {
Paul Bakker96743fc2011-02-12 14:30:57 +00001878#if defined(POLARSSL_PEM_C)
1879 pem_free( &pem );
1880#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00001881 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001882 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001883 }
1884
1885 if( rsa->ver != 0 )
1886 {
Paul Bakker96743fc2011-02-12 14:30:57 +00001887#if defined(POLARSSL_PEM_C)
1888 pem_free( &pem );
1889#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00001890 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001891 return( ret | POLARSSL_ERR_X509_KEY_INVALID_VERSION );
Paul Bakker5121ce52009-01-03 21:22:43 +00001892 }
1893
1894 if( ( ret = asn1_get_mpi( &p, end, &rsa->N ) ) != 0 ||
1895 ( ret = asn1_get_mpi( &p, end, &rsa->E ) ) != 0 ||
1896 ( ret = asn1_get_mpi( &p, end, &rsa->D ) ) != 0 ||
1897 ( ret = asn1_get_mpi( &p, end, &rsa->P ) ) != 0 ||
1898 ( ret = asn1_get_mpi( &p, end, &rsa->Q ) ) != 0 ||
1899 ( ret = asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 ||
1900 ( ret = asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 ||
1901 ( ret = asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 )
1902 {
Paul Bakker96743fc2011-02-12 14:30:57 +00001903#if defined(POLARSSL_PEM_C)
1904 pem_free( &pem );
1905#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00001906 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001907 return( ret | POLARSSL_ERR_X509_KEY_INVALID_FORMAT );
Paul Bakker5121ce52009-01-03 21:22:43 +00001908 }
1909
1910 rsa->len = mpi_size( &rsa->N );
1911
1912 if( p != end )
1913 {
Paul Bakker96743fc2011-02-12 14:30:57 +00001914#if defined(POLARSSL_PEM_C)
1915 pem_free( &pem );
1916#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00001917 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001918 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT |
1919 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001920 }
1921
1922 if( ( ret = rsa_check_privkey( rsa ) ) != 0 )
1923 {
Paul Bakker96743fc2011-02-12 14:30:57 +00001924#if defined(POLARSSL_PEM_C)
1925 pem_free( &pem );
1926#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00001927 rsa_free( rsa );
1928 return( ret );
1929 }
1930
Paul Bakker96743fc2011-02-12 14:30:57 +00001931#if defined(POLARSSL_PEM_C)
1932 pem_free( &pem );
1933#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00001934
1935 return( 0 );
1936}
1937
1938/*
1939 * Load and parse a private RSA key
1940 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001941int x509parse_keyfile( rsa_context *rsa, const char *path, const char *pwd )
Paul Bakker5121ce52009-01-03 21:22:43 +00001942{
1943 int ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001944 size_t n;
1945 unsigned char *buf;
1946
Paul Bakker2b245eb2009-04-19 18:44:26 +00001947 if ( load_file( path, &buf, &n ) )
Paul Bakker5121ce52009-01-03 21:22:43 +00001948 return( 1 );
1949
Paul Bakker5121ce52009-01-03 21:22:43 +00001950 if( pwd == NULL )
1951 ret = x509parse_key( rsa, buf, (int) n, NULL, 0 );
1952 else
1953 ret = x509parse_key( rsa, buf, (int) n,
1954 (unsigned char *) pwd, strlen( pwd ) );
1955
1956 memset( buf, 0, n + 1 );
1957 free( buf );
Paul Bakker5121ce52009-01-03 21:22:43 +00001958
1959 return( ret );
1960}
1961
Paul Bakker1b57b062011-01-06 15:48:19 +00001962/*
Paul Bakker53019ae2011-03-25 13:58:48 +00001963 * Parse a public RSA key
1964 */
Paul Bakker23986e52011-04-24 08:57:21 +00001965int x509parse_public_key( rsa_context *rsa, const unsigned char *key, size_t keylen )
Paul Bakker53019ae2011-03-25 13:58:48 +00001966{
Paul Bakker23986e52011-04-24 08:57:21 +00001967 int ret;
1968 size_t len;
Paul Bakker53019ae2011-03-25 13:58:48 +00001969 unsigned char *p, *end;
1970 x509_buf alg_oid;
1971#if defined(POLARSSL_PEM_C)
1972 pem_context pem;
1973
1974 pem_init( &pem );
1975 ret = pem_read_buffer( &pem,
1976 "-----BEGIN PUBLIC KEY-----",
1977 "-----END PUBLIC KEY-----",
1978 key, NULL, 0, &len );
1979
1980 if( ret == 0 )
1981 {
1982 /*
1983 * Was PEM encoded
1984 */
1985 keylen = pem.buflen;
1986 }
1987 else if( ret != POLARSSL_ERR_PEM_NO_HEADER_PRESENT )
1988 {
1989 pem_free( &pem );
1990 return( ret );
1991 }
1992
1993 p = ( ret == 0 ) ? pem.buf : (unsigned char *) key;
1994#else
1995 p = (unsigned char *) key;
1996#endif
1997 end = p + keylen;
1998
1999 /*
2000 * PublicKeyInfo ::= SEQUENCE {
2001 * algorithm AlgorithmIdentifier,
2002 * PublicKey BIT STRING
2003 * }
2004 *
2005 * AlgorithmIdentifier ::= SEQUENCE {
2006 * algorithm OBJECT IDENTIFIER,
2007 * parameters ANY DEFINED BY algorithm OPTIONAL
2008 * }
2009 *
2010 * RSAPublicKey ::= SEQUENCE {
2011 * modulus INTEGER, -- n
2012 * publicExponent INTEGER -- e
2013 * }
2014 */
2015
2016 if( ( ret = asn1_get_tag( &p, end, &len,
2017 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
2018 {
2019#if defined(POLARSSL_PEM_C)
2020 pem_free( &pem );
2021#endif
2022 rsa_free( rsa );
2023 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
2024 }
2025
2026 if( ( ret = x509_get_pubkey( &p, end, &alg_oid, &rsa->N, &rsa->E ) ) != 0 )
2027 {
2028#if defined(POLARSSL_PEM_C)
2029 pem_free( &pem );
2030#endif
2031 rsa_free( rsa );
2032 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
2033 }
2034
2035 if( ( ret = rsa_check_pubkey( rsa ) ) != 0 )
2036 {
2037#if defined(POLARSSL_PEM_C)
2038 pem_free( &pem );
2039#endif
2040 rsa_free( rsa );
2041 return( ret );
2042 }
2043
2044 rsa->len = mpi_size( &rsa->N );
2045
2046#if defined(POLARSSL_PEM_C)
2047 pem_free( &pem );
2048#endif
2049
2050 return( 0 );
2051}
2052
2053/*
2054 * Load and parse a public RSA key
2055 */
2056int x509parse_public_keyfile( rsa_context *rsa, const char *path )
2057{
2058 int ret;
2059 size_t n;
2060 unsigned char *buf;
2061
2062 if ( load_file( path, &buf, &n ) )
2063 return( 1 );
2064
2065 ret = x509parse_public_key( rsa, buf, (int) n );
2066
2067 memset( buf, 0, n + 1 );
2068 free( buf );
2069
2070 return( ret );
2071}
2072
Paul Bakkereaa89f82011-04-04 21:36:15 +00002073#if defined(POLARSSL_DHM_C)
Paul Bakker53019ae2011-03-25 13:58:48 +00002074/*
Paul Bakker1b57b062011-01-06 15:48:19 +00002075 * Parse DHM parameters
2076 */
Paul Bakker23986e52011-04-24 08:57:21 +00002077int x509parse_dhm( dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen )
Paul Bakker1b57b062011-01-06 15:48:19 +00002078{
Paul Bakker23986e52011-04-24 08:57:21 +00002079 int ret;
2080 size_t len;
Paul Bakker1b57b062011-01-06 15:48:19 +00002081 unsigned char *p, *end;
Paul Bakker96743fc2011-02-12 14:30:57 +00002082#if defined(POLARSSL_PEM_C)
2083 pem_context pem;
Paul Bakker1b57b062011-01-06 15:48:19 +00002084
Paul Bakker96743fc2011-02-12 14:30:57 +00002085 pem_init( &pem );
Paul Bakker1b57b062011-01-06 15:48:19 +00002086
Paul Bakker96743fc2011-02-12 14:30:57 +00002087 ret = pem_read_buffer( &pem,
2088 "-----BEGIN DH PARAMETERS-----",
2089 "-----END DH PARAMETERS-----",
2090 dhmin, NULL, 0, &dhminlen );
2091
2092 if( ret == 0 )
Paul Bakker1b57b062011-01-06 15:48:19 +00002093 {
Paul Bakker96743fc2011-02-12 14:30:57 +00002094 /*
2095 * Was PEM encoded
2096 */
2097 dhminlen = pem.buflen;
Paul Bakker1b57b062011-01-06 15:48:19 +00002098 }
Paul Bakker96743fc2011-02-12 14:30:57 +00002099 else if( ret != POLARSSL_ERR_PEM_NO_HEADER_PRESENT )
Paul Bakker1b57b062011-01-06 15:48:19 +00002100 {
Paul Bakker96743fc2011-02-12 14:30:57 +00002101 pem_free( &pem );
2102 return( ret );
Paul Bakker1b57b062011-01-06 15:48:19 +00002103 }
2104
Paul Bakker96743fc2011-02-12 14:30:57 +00002105 p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
2106#else
2107 p = (unsigned char *) dhmin;
2108#endif
2109 end = p + dhminlen;
2110
Paul Bakker1b57b062011-01-06 15:48:19 +00002111 memset( dhm, 0, sizeof( dhm_context ) );
2112
Paul Bakker1b57b062011-01-06 15:48:19 +00002113 /*
2114 * DHParams ::= SEQUENCE {
2115 * prime INTEGER, -- P
2116 * generator INTEGER, -- g
2117 * }
2118 */
2119 if( ( ret = asn1_get_tag( &p, end, &len,
2120 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
2121 {
Paul Bakker96743fc2011-02-12 14:30:57 +00002122#if defined(POLARSSL_PEM_C)
2123 pem_free( &pem );
2124#endif
Paul Bakker1b57b062011-01-06 15:48:19 +00002125 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
2126 }
2127
2128 end = p + len;
2129
2130 if( ( ret = asn1_get_mpi( &p, end, &dhm->P ) ) != 0 ||
2131 ( ret = asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
2132 {
Paul Bakker96743fc2011-02-12 14:30:57 +00002133#if defined(POLARSSL_PEM_C)
2134 pem_free( &pem );
2135#endif
Paul Bakker1b57b062011-01-06 15:48:19 +00002136 dhm_free( dhm );
2137 return( ret | POLARSSL_ERR_X509_KEY_INVALID_FORMAT );
2138 }
2139
2140 if( p != end )
2141 {
Paul Bakker96743fc2011-02-12 14:30:57 +00002142#if defined(POLARSSL_PEM_C)
2143 pem_free( &pem );
2144#endif
Paul Bakker1b57b062011-01-06 15:48:19 +00002145 dhm_free( dhm );
2146 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT |
2147 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
2148 }
2149
Paul Bakker96743fc2011-02-12 14:30:57 +00002150#if defined(POLARSSL_PEM_C)
2151 pem_free( &pem );
2152#endif
Paul Bakker1b57b062011-01-06 15:48:19 +00002153
2154 return( 0 );
2155}
2156
2157/*
2158 * Load and parse a private RSA key
2159 */
2160int x509parse_dhmfile( dhm_context *dhm, const char *path )
2161{
2162 int ret;
2163 size_t n;
2164 unsigned char *buf;
2165
2166 if ( load_file( path, &buf, &n ) )
2167 return( 1 );
2168
2169 ret = x509parse_dhm( dhm, buf, (int) n);
2170
2171 memset( buf, 0, n + 1 );
2172 free( buf );
2173
2174 return( ret );
2175}
Paul Bakkereaa89f82011-04-04 21:36:15 +00002176#endif /* POLARSSL_DHM_C */
Paul Bakker1b57b062011-01-06 15:48:19 +00002177
Paul Bakker5121ce52009-01-03 21:22:43 +00002178#if defined _MSC_VER && !defined snprintf
Paul Bakkerd98030e2009-05-02 15:13:40 +00002179#include <stdarg.h>
2180
2181#if !defined vsnprintf
2182#define vsnprintf _vsnprintf
2183#endif // vsnprintf
2184
2185/*
2186 * Windows _snprintf and _vsnprintf are not compatible to linux versions.
2187 * Result value is not size of buffer needed, but -1 if no fit is possible.
2188 *
2189 * This fuction tries to 'fix' this by at least suggesting enlarging the
2190 * size by 20.
2191 */
2192int compat_snprintf(char *str, size_t size, const char *format, ...)
2193{
2194 va_list ap;
2195 int res = -1;
2196
2197 va_start( ap, format );
2198
2199 res = vsnprintf( str, size, format, ap );
2200
2201 va_end( ap );
2202
2203 // No quick fix possible
2204 if ( res < 0 )
Paul Bakker23986e52011-04-24 08:57:21 +00002205 return( (int) size + 20 );
Paul Bakkerd98030e2009-05-02 15:13:40 +00002206
2207 return res;
2208}
2209
2210#define snprintf compat_snprintf
Paul Bakker5121ce52009-01-03 21:22:43 +00002211#endif
2212
Paul Bakkerd98030e2009-05-02 15:13:40 +00002213#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL -2
2214
2215#define SAFE_SNPRINTF() \
2216{ \
2217 if( ret == -1 ) \
2218 return( -1 ); \
2219 \
Paul Bakker23986e52011-04-24 08:57:21 +00002220 if ( (unsigned int) ret > n ) { \
Paul Bakkerd98030e2009-05-02 15:13:40 +00002221 p[n - 1] = '\0'; \
2222 return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
2223 } \
2224 \
Paul Bakker23986e52011-04-24 08:57:21 +00002225 n -= (unsigned int) ret; \
2226 p += (unsigned int) ret; \
Paul Bakkerd98030e2009-05-02 15:13:40 +00002227}
2228
Paul Bakker5121ce52009-01-03 21:22:43 +00002229/*
2230 * Store the name in printable form into buf; no more
Paul Bakkerd98030e2009-05-02 15:13:40 +00002231 * than size characters will be written
Paul Bakker5121ce52009-01-03 21:22:43 +00002232 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00002233int x509parse_dn_gets( char *buf, size_t size, const x509_name *dn )
Paul Bakker5121ce52009-01-03 21:22:43 +00002234{
Paul Bakker23986e52011-04-24 08:57:21 +00002235 int ret;
2236 size_t i, n;
Paul Bakker5121ce52009-01-03 21:22:43 +00002237 unsigned char c;
Paul Bakkerff60ee62010-03-16 21:09:09 +00002238 const x509_name *name;
Paul Bakker5121ce52009-01-03 21:22:43 +00002239 char s[128], *p;
2240
2241 memset( s, 0, sizeof( s ) );
2242
2243 name = dn;
2244 p = buf;
Paul Bakkerd98030e2009-05-02 15:13:40 +00002245 n = size;
Paul Bakker5121ce52009-01-03 21:22:43 +00002246
2247 while( name != NULL )
2248 {
Paul Bakker74111d32011-01-15 16:57:55 +00002249 if( name != dn )
2250 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00002251 ret = snprintf( p, n, ", " );
2252 SAFE_SNPRINTF();
2253 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002254
2255 if( memcmp( name->oid.p, OID_X520, 2 ) == 0 )
2256 {
2257 switch( name->oid.p[2] )
2258 {
2259 case X520_COMMON_NAME:
Paul Bakkerd98030e2009-05-02 15:13:40 +00002260 ret = snprintf( p, n, "CN=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002261
2262 case X520_COUNTRY:
Paul Bakkerd98030e2009-05-02 15:13:40 +00002263 ret = snprintf( p, n, "C=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002264
2265 case X520_LOCALITY:
Paul Bakkerd98030e2009-05-02 15:13:40 +00002266 ret = snprintf( p, n, "L=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002267
2268 case X520_STATE:
Paul Bakkerd98030e2009-05-02 15:13:40 +00002269 ret = snprintf( p, n, "ST=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002270
2271 case X520_ORGANIZATION:
Paul Bakkerd98030e2009-05-02 15:13:40 +00002272 ret = snprintf( p, n, "O=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002273
2274 case X520_ORG_UNIT:
Paul Bakkerd98030e2009-05-02 15:13:40 +00002275 ret = snprintf( p, n, "OU=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002276
2277 default:
Paul Bakkerd98030e2009-05-02 15:13:40 +00002278 ret = snprintf( p, n, "0x%02X=",
Paul Bakker5121ce52009-01-03 21:22:43 +00002279 name->oid.p[2] );
2280 break;
2281 }
Paul Bakkerd98030e2009-05-02 15:13:40 +00002282 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002283 }
2284 else if( memcmp( name->oid.p, OID_PKCS9, 8 ) == 0 )
2285 {
2286 switch( name->oid.p[8] )
2287 {
2288 case PKCS9_EMAIL:
Paul Bakkerd98030e2009-05-02 15:13:40 +00002289 ret = snprintf( p, n, "emailAddress=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002290
2291 default:
Paul Bakkerd98030e2009-05-02 15:13:40 +00002292 ret = snprintf( p, n, "0x%02X=",
Paul Bakker5121ce52009-01-03 21:22:43 +00002293 name->oid.p[8] );
2294 break;
2295 }
Paul Bakkerd98030e2009-05-02 15:13:40 +00002296 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002297 }
2298 else
Paul Bakker74111d32011-01-15 16:57:55 +00002299 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00002300 ret = snprintf( p, n, "\?\?=" );
Paul Bakker74111d32011-01-15 16:57:55 +00002301 SAFE_SNPRINTF();
Paul Bakkerd98030e2009-05-02 15:13:40 +00002302 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002303
2304 for( i = 0; i < name->val.len; i++ )
2305 {
2306 if( i >= (int) sizeof( s ) - 1 )
2307 break;
2308
2309 c = name->val.p[i];
2310 if( c < 32 || c == 127 || ( c > 128 && c < 160 ) )
2311 s[i] = '?';
2312 else s[i] = c;
2313 }
2314 s[i] = '\0';
Paul Bakkerd98030e2009-05-02 15:13:40 +00002315 ret = snprintf( p, n, "%s", s );
2316 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002317 name = name->next;
2318 }
2319
Paul Bakker23986e52011-04-24 08:57:21 +00002320 return( (int) ( size - n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002321}
2322
2323/*
Paul Bakkerdd476992011-01-16 21:34:59 +00002324 * Store the serial in printable form into buf; no more
2325 * than size characters will be written
2326 */
2327int x509parse_serial_gets( char *buf, size_t size, const x509_buf *serial )
2328{
Paul Bakker23986e52011-04-24 08:57:21 +00002329 int ret;
2330 size_t i, n, nr;
Paul Bakkerdd476992011-01-16 21:34:59 +00002331 char *p;
2332
2333 p = buf;
2334 n = size;
2335
2336 nr = ( serial->len <= 32 )
2337 ? serial->len : 32;
2338
2339 for( i = 0; i < nr; i++ )
2340 {
2341 ret = snprintf( p, n, "%02X%s",
2342 serial->p[i], ( i < nr - 1 ) ? ":" : "" );
2343 SAFE_SNPRINTF();
2344 }
2345
Paul Bakker23986e52011-04-24 08:57:21 +00002346 return( (int) ( size - n ) );
Paul Bakkerdd476992011-01-16 21:34:59 +00002347}
2348
2349/*
Paul Bakkerd98030e2009-05-02 15:13:40 +00002350 * Return an informational string about the certificate.
Paul Bakker5121ce52009-01-03 21:22:43 +00002351 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00002352int x509parse_cert_info( char *buf, size_t size, const char *prefix,
2353 const x509_cert *crt )
Paul Bakker5121ce52009-01-03 21:22:43 +00002354{
Paul Bakker23986e52011-04-24 08:57:21 +00002355 int ret;
2356 size_t n;
Paul Bakkerd98030e2009-05-02 15:13:40 +00002357 char *p;
Paul Bakker5121ce52009-01-03 21:22:43 +00002358
2359 p = buf;
Paul Bakkerd98030e2009-05-02 15:13:40 +00002360 n = size;
Paul Bakker5121ce52009-01-03 21:22:43 +00002361
Paul Bakkerd98030e2009-05-02 15:13:40 +00002362 ret = snprintf( p, n, "%scert. version : %d\n",
Paul Bakker5121ce52009-01-03 21:22:43 +00002363 prefix, crt->version );
Paul Bakkerd98030e2009-05-02 15:13:40 +00002364 SAFE_SNPRINTF();
2365 ret = snprintf( p, n, "%sserial number : ",
Paul Bakker5121ce52009-01-03 21:22:43 +00002366 prefix );
Paul Bakkerd98030e2009-05-02 15:13:40 +00002367 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002368
Paul Bakkerdd476992011-01-16 21:34:59 +00002369 ret = x509parse_serial_gets( p, n, &crt->serial);
2370 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002371
Paul Bakkerd98030e2009-05-02 15:13:40 +00002372 ret = snprintf( p, n, "\n%sissuer name : ", prefix );
2373 SAFE_SNPRINTF();
2374 ret = x509parse_dn_gets( p, n, &crt->issuer );
2375 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002376
Paul Bakkerd98030e2009-05-02 15:13:40 +00002377 ret = snprintf( p, n, "\n%ssubject name : ", prefix );
2378 SAFE_SNPRINTF();
2379 ret = x509parse_dn_gets( p, n, &crt->subject );
2380 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002381
Paul Bakkerd98030e2009-05-02 15:13:40 +00002382 ret = snprintf( p, n, "\n%sissued on : " \
Paul Bakker5121ce52009-01-03 21:22:43 +00002383 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
2384 crt->valid_from.year, crt->valid_from.mon,
2385 crt->valid_from.day, crt->valid_from.hour,
2386 crt->valid_from.min, crt->valid_from.sec );
Paul Bakkerd98030e2009-05-02 15:13:40 +00002387 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002388
Paul Bakkerd98030e2009-05-02 15:13:40 +00002389 ret = snprintf( p, n, "\n%sexpires on : " \
Paul Bakker5121ce52009-01-03 21:22:43 +00002390 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
2391 crt->valid_to.year, crt->valid_to.mon,
2392 crt->valid_to.day, crt->valid_to.hour,
2393 crt->valid_to.min, crt->valid_to.sec );
Paul Bakkerd98030e2009-05-02 15:13:40 +00002394 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002395
Paul Bakkerd98030e2009-05-02 15:13:40 +00002396 ret = snprintf( p, n, "\n%ssigned using : RSA+", prefix );
2397 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002398
Paul Bakker27d66162010-03-17 06:56:01 +00002399 switch( crt->sig_alg )
Paul Bakker5121ce52009-01-03 21:22:43 +00002400 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00002401 case SIG_RSA_MD2 : ret = snprintf( p, n, "MD2" ); break;
2402 case SIG_RSA_MD4 : ret = snprintf( p, n, "MD4" ); break;
2403 case SIG_RSA_MD5 : ret = snprintf( p, n, "MD5" ); break;
2404 case SIG_RSA_SHA1 : ret = snprintf( p, n, "SHA1" ); break;
2405 case SIG_RSA_SHA224 : ret = snprintf( p, n, "SHA224" ); break;
2406 case SIG_RSA_SHA256 : ret = snprintf( p, n, "SHA256" ); break;
2407 case SIG_RSA_SHA384 : ret = snprintf( p, n, "SHA384" ); break;
2408 case SIG_RSA_SHA512 : ret = snprintf( p, n, "SHA512" ); break;
2409 default: ret = snprintf( p, n, "???" ); break;
2410 }
2411 SAFE_SNPRINTF();
2412
2413 ret = snprintf( p, n, "\n%sRSA key size : %d bits\n", prefix,
Paul Bakkerf4f69682011-04-24 16:08:12 +00002414 (int) crt->rsa.N.n * (int) sizeof( unsigned long ) * 8 );
Paul Bakkerd98030e2009-05-02 15:13:40 +00002415 SAFE_SNPRINTF();
2416
Paul Bakker23986e52011-04-24 08:57:21 +00002417 return( (int) ( size - n ) );
Paul Bakkerd98030e2009-05-02 15:13:40 +00002418}
2419
Paul Bakker74111d32011-01-15 16:57:55 +00002420/* Compare a given OID string with an OID x509_buf * */
2421#define OID_CMP(oid_str, oid_buf) \
2422 ( ( OID_SIZE(oid_str) == (oid_buf)->len ) && \
2423 memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) == 0)
2424
2425/*
2426 * Return an informational string describing the given OID
2427 */
2428const char *x509_oid_get_description( x509_buf *oid )
2429{
2430 if ( oid == NULL )
2431 return ( NULL );
2432
2433 else if( OID_CMP( OID_SERVER_AUTH, oid ) )
2434 return( STRING_SERVER_AUTH );
2435
2436 else if( OID_CMP( OID_CLIENT_AUTH, oid ) )
2437 return( STRING_CLIENT_AUTH );
2438
2439 else if( OID_CMP( OID_CODE_SIGNING, oid ) )
2440 return( STRING_CODE_SIGNING );
2441
2442 else if( OID_CMP( OID_EMAIL_PROTECTION, oid ) )
2443 return( STRING_EMAIL_PROTECTION );
2444
2445 else if( OID_CMP( OID_TIME_STAMPING, oid ) )
2446 return( STRING_TIME_STAMPING );
2447
2448 else if( OID_CMP( OID_OCSP_SIGNING, oid ) )
2449 return( STRING_OCSP_SIGNING );
2450
2451 return( NULL );
2452}
2453
2454/* Return the x.y.z.... style numeric string for the given OID */
2455int x509_oid_get_numeric_string( char *buf, size_t size, x509_buf *oid )
2456{
Paul Bakker23986e52011-04-24 08:57:21 +00002457 int ret;
2458 size_t i, n;
Paul Bakker74111d32011-01-15 16:57:55 +00002459 unsigned int value;
2460 char *p;
2461
2462 p = buf;
2463 n = size;
2464
2465 /* First byte contains first two dots */
2466 if( oid->len > 0 )
2467 {
2468 ret = snprintf( p, n, "%d.%d", oid->p[0]/40, oid->p[0]%40 );
2469 SAFE_SNPRINTF();
2470 }
2471
2472 /* TODO: value can overflow in value. */
2473 value = 0;
Paul Bakker23986e52011-04-24 08:57:21 +00002474 for( i = 1; i < oid->len; i++ )
Paul Bakker74111d32011-01-15 16:57:55 +00002475 {
2476 value <<= 7;
2477 value += oid->p[i] & 0x7F;
2478
2479 if( !( oid->p[i] & 0x80 ) )
2480 {
2481 /* Last byte */
2482 ret = snprintf( p, n, ".%d", value );
2483 SAFE_SNPRINTF();
2484 value = 0;
2485 }
2486 }
2487
Paul Bakker23986e52011-04-24 08:57:21 +00002488 return( (int) ( size - n ) );
Paul Bakker74111d32011-01-15 16:57:55 +00002489}
2490
Paul Bakkerd98030e2009-05-02 15:13:40 +00002491/*
2492 * Return an informational string about the CRL.
2493 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00002494int x509parse_crl_info( char *buf, size_t size, const char *prefix,
2495 const x509_crl *crl )
Paul Bakkerd98030e2009-05-02 15:13:40 +00002496{
Paul Bakker23986e52011-04-24 08:57:21 +00002497 int ret;
2498 size_t i, n, nr;
Paul Bakkerd98030e2009-05-02 15:13:40 +00002499 char *p;
Paul Bakkerff60ee62010-03-16 21:09:09 +00002500 const x509_crl_entry *entry;
Paul Bakkerd98030e2009-05-02 15:13:40 +00002501
2502 p = buf;
2503 n = size;
2504
2505 ret = snprintf( p, n, "%sCRL version : %d",
2506 prefix, crl->version );
2507 SAFE_SNPRINTF();
2508
2509 ret = snprintf( p, n, "\n%sissuer name : ", prefix );
2510 SAFE_SNPRINTF();
2511 ret = x509parse_dn_gets( p, n, &crl->issuer );
2512 SAFE_SNPRINTF();
2513
2514 ret = snprintf( p, n, "\n%sthis update : " \
2515 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
2516 crl->this_update.year, crl->this_update.mon,
2517 crl->this_update.day, crl->this_update.hour,
2518 crl->this_update.min, crl->this_update.sec );
2519 SAFE_SNPRINTF();
2520
2521 ret = snprintf( p, n, "\n%snext update : " \
2522 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
2523 crl->next_update.year, crl->next_update.mon,
2524 crl->next_update.day, crl->next_update.hour,
2525 crl->next_update.min, crl->next_update.sec );
2526 SAFE_SNPRINTF();
2527
2528 entry = &crl->entry;
2529
2530 ret = snprintf( p, n, "\n%sRevoked certificates:",
2531 prefix );
2532 SAFE_SNPRINTF();
2533
Paul Bakker9be19372009-07-27 20:21:53 +00002534 while( entry != NULL && entry->raw.len != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +00002535 {
2536 ret = snprintf( p, n, "\n%sserial number: ",
2537 prefix );
2538 SAFE_SNPRINTF();
2539
2540 nr = ( entry->serial.len <= 32 )
2541 ? entry->serial.len : 32;
2542
Paul Bakker74111d32011-01-15 16:57:55 +00002543 for( i = 0; i < nr; i++ )
2544 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00002545 ret = snprintf( p, n, "%02X%s",
2546 entry->serial.p[i], ( i < nr - 1 ) ? ":" : "" );
2547 SAFE_SNPRINTF();
2548 }
2549
2550 ret = snprintf( p, n, " revocation date: " \
2551 "%04d-%02d-%02d %02d:%02d:%02d",
2552 entry->revocation_date.year, entry->revocation_date.mon,
2553 entry->revocation_date.day, entry->revocation_date.hour,
2554 entry->revocation_date.min, entry->revocation_date.sec );
2555 SAFE_SNPRINTF();
2556
2557 entry = entry->next;
Paul Bakker5121ce52009-01-03 21:22:43 +00002558 }
2559
Paul Bakkerd98030e2009-05-02 15:13:40 +00002560 ret = snprintf( p, n, "\n%ssigned using : RSA+", prefix );
2561 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002562
Paul Bakker27d66162010-03-17 06:56:01 +00002563 switch( crl->sig_alg )
Paul Bakkerd98030e2009-05-02 15:13:40 +00002564 {
2565 case SIG_RSA_MD2 : ret = snprintf( p, n, "MD2" ); break;
2566 case SIG_RSA_MD4 : ret = snprintf( p, n, "MD4" ); break;
2567 case SIG_RSA_MD5 : ret = snprintf( p, n, "MD5" ); break;
2568 case SIG_RSA_SHA1 : ret = snprintf( p, n, "SHA1" ); break;
2569 case SIG_RSA_SHA224 : ret = snprintf( p, n, "SHA224" ); break;
2570 case SIG_RSA_SHA256 : ret = snprintf( p, n, "SHA256" ); break;
2571 case SIG_RSA_SHA384 : ret = snprintf( p, n, "SHA384" ); break;
2572 case SIG_RSA_SHA512 : ret = snprintf( p, n, "SHA512" ); break;
2573 default: ret = snprintf( p, n, "???" ); break;
2574 }
2575 SAFE_SNPRINTF();
2576
Paul Bakker1e27bb22009-07-19 20:25:25 +00002577 ret = snprintf( p, n, "\n" );
2578 SAFE_SNPRINTF();
2579
Paul Bakker23986e52011-04-24 08:57:21 +00002580 return( (int) ( size - n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002581}
2582
2583/*
Paul Bakker40ea7de2009-05-03 10:18:48 +00002584 * Return 0 if the x509_time is still valid, or 1 otherwise.
Paul Bakker5121ce52009-01-03 21:22:43 +00002585 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00002586int x509parse_time_expired( const x509_time *to )
Paul Bakker5121ce52009-01-03 21:22:43 +00002587{
2588 struct tm *lt;
2589 time_t tt;
2590
2591 tt = time( NULL );
2592 lt = localtime( &tt );
2593
Paul Bakker40ea7de2009-05-03 10:18:48 +00002594 if( lt->tm_year > to->year - 1900 )
2595 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002596
Paul Bakker40ea7de2009-05-03 10:18:48 +00002597 if( lt->tm_year == to->year - 1900 &&
2598 lt->tm_mon > to->mon - 1 )
2599 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002600
Paul Bakker40ea7de2009-05-03 10:18:48 +00002601 if( lt->tm_year == to->year - 1900 &&
2602 lt->tm_mon == to->mon - 1 &&
2603 lt->tm_mday > to->day )
2604 return( 1 );
2605
Paul Bakkerb6194992011-01-16 21:40:22 +00002606 if( lt->tm_year == to->year - 1900 &&
2607 lt->tm_mon == to->mon - 1 &&
2608 lt->tm_mday == to->day &&
2609 lt->tm_hour > to->hour - 1)
2610 return( 1 );
2611
2612 if( lt->tm_year == to->year - 1900 &&
2613 lt->tm_mon == to->mon - 1 &&
2614 lt->tm_mday == to->day &&
2615 lt->tm_hour == to->hour - 1 &&
2616 lt->tm_min > to->min - 1 )
2617 return( 1 );
2618
2619 if( lt->tm_year == to->year - 1900 &&
2620 lt->tm_mon == to->mon - 1 &&
2621 lt->tm_mday == to->day &&
2622 lt->tm_hour == to->hour - 1 &&
2623 lt->tm_min == to->min - 1 &&
2624 lt->tm_sec > to->sec - 1 )
2625 return( 1 );
2626
Paul Bakker40ea7de2009-05-03 10:18:48 +00002627 return( 0 );
2628}
2629
2630/*
2631 * Return 1 if the certificate is revoked, or 0 otherwise.
2632 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00002633int x509parse_revoked( const x509_cert *crt, const x509_crl *crl )
Paul Bakker40ea7de2009-05-03 10:18:48 +00002634{
Paul Bakkerff60ee62010-03-16 21:09:09 +00002635 const x509_crl_entry *cur = &crl->entry;
Paul Bakker40ea7de2009-05-03 10:18:48 +00002636
2637 while( cur != NULL && cur->serial.len != 0 )
2638 {
Paul Bakkera056efc2011-01-16 21:38:35 +00002639 if( crt->serial.len == cur->serial.len &&
2640 memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 )
Paul Bakker40ea7de2009-05-03 10:18:48 +00002641 {
2642 if( x509parse_time_expired( &cur->revocation_date ) )
2643 return( 1 );
2644 }
2645
2646 cur = cur->next;
2647 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002648
2649 return( 0 );
2650}
2651
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002652/*
2653 * Wrapper for x509 hashes.
2654 *
Paul Bakker0f5f72e2011-01-18 14:58:55 +00002655 * \param out Buffer to receive the hash (Should be at least 64 bytes)
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002656 */
Paul Bakker23986e52011-04-24 08:57:21 +00002657static void x509_hash( const unsigned char *in, size_t len, int alg,
Paul Bakker5121ce52009-01-03 21:22:43 +00002658 unsigned char *out )
2659{
2660 switch( alg )
2661 {
Paul Bakker40e46942009-01-03 21:51:57 +00002662#if defined(POLARSSL_MD2_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00002663 case SIG_RSA_MD2 : md2( in, len, out ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002664#endif
Paul Bakker40e46942009-01-03 21:51:57 +00002665#if defined(POLARSSL_MD4_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00002666 case SIG_RSA_MD4 : md4( in, len, out ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002667#endif
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002668#if defined(POLARSSL_MD5_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00002669 case SIG_RSA_MD5 : md5( in, len, out ); break;
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002670#endif
2671#if defined(POLARSSL_SHA1_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00002672 case SIG_RSA_SHA1 : sha1( in, len, out ); break;
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002673#endif
Paul Bakker4593aea2009-02-09 22:32:35 +00002674#if defined(POLARSSL_SHA2_C)
2675 case SIG_RSA_SHA224 : sha2( in, len, out, 1 ); break;
2676 case SIG_RSA_SHA256 : sha2( in, len, out, 0 ); break;
2677#endif
Paul Bakkerfe1aea72009-10-03 20:09:14 +00002678#if defined(POLARSSL_SHA4_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00002679 case SIG_RSA_SHA384 : sha4( in, len, out, 1 ); break;
2680 case SIG_RSA_SHA512 : sha4( in, len, out, 0 ); break;
2681#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00002682 default:
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002683 memset( out, '\xFF', 64 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002684 break;
2685 }
2686}
2687
2688/*
Paul Bakker76fd75a2011-01-16 21:12:10 +00002689 * Check that the given certificate is valid accoring to the CRL.
2690 */
2691static int x509parse_verifycrl(x509_cert *crt, x509_cert *ca,
2692 x509_crl *crl_list)
2693{
2694 int flags = 0;
2695 int hash_id;
2696 unsigned char hash[64];
2697
2698 /*
2699 * TODO: What happens if no CRL is present?
2700 * Suggestion: Revocation state should be unknown if no CRL is present.
2701 * For backwards compatibility this is not yet implemented.
2702 */
2703
2704 while( ca != NULL && crl_list != NULL && crl_list->version != 0 )
2705 {
2706 if( crl_list->issuer_raw.len != ca->subject_raw.len ||
2707 memcmp( crl_list->issuer_raw.p, ca->subject_raw.p,
2708 crl_list->issuer_raw.len ) != 0 )
2709 {
2710 crl_list = crl_list->next;
2711 continue;
2712 }
2713
2714 /*
2715 * Check if CRL is correctly signed by the trusted CA
2716 */
2717 hash_id = crl_list->sig_alg;
2718
2719 x509_hash( crl_list->tbs.p, crl_list->tbs.len, hash_id, hash );
2720
2721 if( !rsa_pkcs1_verify( &ca->rsa, RSA_PUBLIC, hash_id,
2722 0, hash, crl_list->sig.p ) == 0 )
2723 {
2724 /*
2725 * CRL is not trusted
2726 */
2727 flags |= BADCRL_NOT_TRUSTED;
2728 break;
2729 }
2730
2731 /*
2732 * Check for validity of CRL (Do not drop out)
2733 */
2734 if( x509parse_time_expired( &crl_list->next_update ) )
2735 flags |= BADCRL_EXPIRED;
2736
2737 /*
2738 * Check if certificate is revoked
2739 */
2740 if( x509parse_revoked(crt, crl_list) )
2741 {
2742 flags |= BADCERT_REVOKED;
2743 break;
2744 }
2745
2746 crl_list = crl_list->next;
2747 }
2748 return flags;
2749}
2750
2751/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002752 * Verify the certificate validity
2753 */
2754int x509parse_verify( x509_cert *crt,
2755 x509_cert *trust_ca,
Paul Bakker40ea7de2009-05-03 10:18:48 +00002756 x509_crl *ca_crl,
Paul Bakkerb63b0af2011-01-13 17:54:59 +00002757 const char *cn, int *flags,
2758 int (*f_vrfy)(void *, x509_cert *, int, int),
2759 void *p_vrfy )
Paul Bakker5121ce52009-01-03 21:22:43 +00002760{
Paul Bakker23986e52011-04-24 08:57:21 +00002761 size_t cn_len;
Paul Bakker5121ce52009-01-03 21:22:43 +00002762 int hash_id;
2763 int pathlen;
Paul Bakker76fd75a2011-01-16 21:12:10 +00002764 x509_cert *parent;
Paul Bakker5121ce52009-01-03 21:22:43 +00002765 x509_name *name;
Paul Bakker4593aea2009-02-09 22:32:35 +00002766 unsigned char hash[64];
Paul Bakker5121ce52009-01-03 21:22:43 +00002767
Paul Bakker40ea7de2009-05-03 10:18:48 +00002768 *flags = 0;
2769
2770 if( x509parse_time_expired( &crt->valid_to ) )
2771 *flags = BADCERT_EXPIRED;
Paul Bakker5121ce52009-01-03 21:22:43 +00002772
2773 if( cn != NULL )
2774 {
2775 name = &crt->subject;
2776 cn_len = strlen( cn );
2777
2778 while( name != NULL )
2779 {
2780 if( memcmp( name->oid.p, OID_CN, 3 ) == 0 &&
2781 memcmp( name->val.p, cn, cn_len ) == 0 &&
2782 name->val.len == cn_len )
2783 break;
2784
2785 name = name->next;
2786 }
2787
2788 if( name == NULL )
2789 *flags |= BADCERT_CN_MISMATCH;
2790 }
2791
Paul Bakker5121ce52009-01-03 21:22:43 +00002792 /*
2793 * Iterate upwards in the given cert chain,
2794 * ignoring any upper cert with CA != TRUE.
2795 */
Paul Bakker76fd75a2011-01-16 21:12:10 +00002796 parent = crt->next;
Paul Bakker5121ce52009-01-03 21:22:43 +00002797
2798 pathlen = 1;
2799
Paul Bakker76fd75a2011-01-16 21:12:10 +00002800 while( parent != NULL && parent->version != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002801 {
Paul Bakker76fd75a2011-01-16 21:12:10 +00002802 if( parent->ca_istrue == 0 ||
2803 crt->issuer_raw.len != parent->subject_raw.len ||
2804 memcmp( crt->issuer_raw.p, parent->subject_raw.p,
Paul Bakker5121ce52009-01-03 21:22:43 +00002805 crt->issuer_raw.len ) != 0 )
2806 {
Paul Bakker76fd75a2011-01-16 21:12:10 +00002807 parent = parent->next;
Paul Bakker5121ce52009-01-03 21:22:43 +00002808 continue;
2809 }
2810
Paul Bakker27d66162010-03-17 06:56:01 +00002811 hash_id = crt->sig_alg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002812
2813 x509_hash( crt->tbs.p, crt->tbs.len, hash_id, hash );
2814
Paul Bakker76fd75a2011-01-16 21:12:10 +00002815 if( rsa_pkcs1_verify( &parent->rsa, RSA_PUBLIC, hash_id, 0, hash,
2816 crt->sig.p ) != 0 )
2817 *flags |= BADCERT_NOT_TRUSTED;
2818
2819 /* Check trusted CA's CRL for the given crt */
2820 *flags |= x509parse_verifycrl(crt, parent, ca_crl);
Paul Bakkerb63b0af2011-01-13 17:54:59 +00002821
2822 /* crt is verified to be a child of the parent cur, call verify callback */
Paul Bakker74111d32011-01-15 16:57:55 +00002823 if( NULL != f_vrfy )
2824 {
Paul Bakker76fd75a2011-01-16 21:12:10 +00002825 if( f_vrfy( p_vrfy, crt, pathlen - 1, ( *flags == 0 ) ) != 0 )
Paul Bakkerb63b0af2011-01-13 17:54:59 +00002826 return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
Paul Bakker76fd75a2011-01-16 21:12:10 +00002827 else
2828 *flags = 0;
Paul Bakkerb63b0af2011-01-13 17:54:59 +00002829 }
Paul Bakker76fd75a2011-01-16 21:12:10 +00002830 else if( *flags != 0 )
2831 return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +00002832
2833 pathlen++;
2834
Paul Bakker76fd75a2011-01-16 21:12:10 +00002835 crt = parent;
2836 parent = crt->next;
Paul Bakker5121ce52009-01-03 21:22:43 +00002837 }
2838
2839 /*
Paul Bakker76fd75a2011-01-16 21:12:10 +00002840 * Attempt to validate topmost cert with our CA chain.
Paul Bakker5121ce52009-01-03 21:22:43 +00002841 */
Paul Bakker76fd75a2011-01-16 21:12:10 +00002842 *flags |= BADCERT_NOT_TRUSTED;
2843
Paul Bakker7c6d4a42009-03-28 20:35:47 +00002844 while( trust_ca != NULL && trust_ca->version != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002845 {
2846 if( crt->issuer_raw.len != trust_ca->subject_raw.len ||
2847 memcmp( crt->issuer_raw.p, trust_ca->subject_raw.p,
2848 crt->issuer_raw.len ) != 0 )
2849 {
2850 trust_ca = trust_ca->next;
2851 continue;
2852 }
2853
2854 if( trust_ca->max_pathlen > 0 &&
2855 trust_ca->max_pathlen < pathlen )
2856 break;
2857
Paul Bakker27d66162010-03-17 06:56:01 +00002858 hash_id = crt->sig_alg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002859
2860 x509_hash( crt->tbs.p, crt->tbs.len, hash_id, hash );
2861
2862 if( rsa_pkcs1_verify( &trust_ca->rsa, RSA_PUBLIC, hash_id,
2863 0, hash, crt->sig.p ) == 0 )
2864 {
2865 /*
2866 * cert. is signed by a trusted CA
2867 */
2868 *flags &= ~BADCERT_NOT_TRUSTED;
2869 break;
2870 }
2871
2872 trust_ca = trust_ca->next;
2873 }
2874
Paul Bakker76fd75a2011-01-16 21:12:10 +00002875 /* Check trusted CA's CRL for the given crt */
2876 *flags |= x509parse_verifycrl( crt, trust_ca, ca_crl );
Paul Bakkerb63b0af2011-01-13 17:54:59 +00002877
2878 /* Verification succeeded, call callback on top cert */
Paul Bakker74111d32011-01-15 16:57:55 +00002879 if( NULL != f_vrfy )
2880 {
Paul Bakker76fd75a2011-01-16 21:12:10 +00002881 if( f_vrfy(p_vrfy, crt, pathlen-1, ( *flags == 0 ) ) != 0 )
Paul Bakkerb63b0af2011-01-13 17:54:59 +00002882 return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
Paul Bakker76fd75a2011-01-16 21:12:10 +00002883 else
2884 *flags = 0;
Paul Bakkerb63b0af2011-01-13 17:54:59 +00002885 }
Paul Bakker76fd75a2011-01-16 21:12:10 +00002886 else if( *flags != 0 )
2887 return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
Paul Bakkerb63b0af2011-01-13 17:54:59 +00002888
Paul Bakker5121ce52009-01-03 21:22:43 +00002889 return( 0 );
2890}
2891
2892/*
2893 * Unallocate all certificate data
2894 */
2895void x509_free( x509_cert *crt )
2896{
2897 x509_cert *cert_cur = crt;
2898 x509_cert *cert_prv;
2899 x509_name *name_cur;
2900 x509_name *name_prv;
Paul Bakker74111d32011-01-15 16:57:55 +00002901 x509_sequence *seq_cur;
2902 x509_sequence *seq_prv;
Paul Bakker5121ce52009-01-03 21:22:43 +00002903
2904 if( crt == NULL )
2905 return;
2906
2907 do
2908 {
2909 rsa_free( &cert_cur->rsa );
2910
2911 name_cur = cert_cur->issuer.next;
2912 while( name_cur != NULL )
2913 {
2914 name_prv = name_cur;
2915 name_cur = name_cur->next;
2916 memset( name_prv, 0, sizeof( x509_name ) );
2917 free( name_prv );
2918 }
2919
2920 name_cur = cert_cur->subject.next;
2921 while( name_cur != NULL )
2922 {
2923 name_prv = name_cur;
2924 name_cur = name_cur->next;
2925 memset( name_prv, 0, sizeof( x509_name ) );
2926 free( name_prv );
2927 }
2928
Paul Bakker74111d32011-01-15 16:57:55 +00002929 seq_cur = cert_cur->ext_key_usage.next;
2930 while( seq_cur != NULL )
2931 {
2932 seq_prv = seq_cur;
2933 seq_cur = seq_cur->next;
2934 memset( seq_prv, 0, sizeof( x509_sequence ) );
2935 free( seq_prv );
2936 }
2937
Paul Bakker5121ce52009-01-03 21:22:43 +00002938 if( cert_cur->raw.p != NULL )
2939 {
2940 memset( cert_cur->raw.p, 0, cert_cur->raw.len );
2941 free( cert_cur->raw.p );
2942 }
2943
2944 cert_cur = cert_cur->next;
2945 }
2946 while( cert_cur != NULL );
2947
2948 cert_cur = crt;
2949 do
2950 {
2951 cert_prv = cert_cur;
2952 cert_cur = cert_cur->next;
2953
2954 memset( cert_prv, 0, sizeof( x509_cert ) );
2955 if( cert_prv != crt )
2956 free( cert_prv );
2957 }
2958 while( cert_cur != NULL );
2959}
2960
Paul Bakkerd98030e2009-05-02 15:13:40 +00002961/*
2962 * Unallocate all CRL data
2963 */
2964void x509_crl_free( x509_crl *crl )
2965{
2966 x509_crl *crl_cur = crl;
2967 x509_crl *crl_prv;
2968 x509_name *name_cur;
2969 x509_name *name_prv;
2970 x509_crl_entry *entry_cur;
2971 x509_crl_entry *entry_prv;
2972
2973 if( crl == NULL )
2974 return;
2975
2976 do
2977 {
2978 name_cur = crl_cur->issuer.next;
2979 while( name_cur != NULL )
2980 {
2981 name_prv = name_cur;
2982 name_cur = name_cur->next;
2983 memset( name_prv, 0, sizeof( x509_name ) );
2984 free( name_prv );
2985 }
2986
2987 entry_cur = crl_cur->entry.next;
2988 while( entry_cur != NULL )
2989 {
2990 entry_prv = entry_cur;
2991 entry_cur = entry_cur->next;
2992 memset( entry_prv, 0, sizeof( x509_crl_entry ) );
2993 free( entry_prv );
2994 }
2995
2996 if( crl_cur->raw.p != NULL )
2997 {
2998 memset( crl_cur->raw.p, 0, crl_cur->raw.len );
2999 free( crl_cur->raw.p );
3000 }
3001
3002 crl_cur = crl_cur->next;
3003 }
3004 while( crl_cur != NULL );
3005
3006 crl_cur = crl;
3007 do
3008 {
3009 crl_prv = crl_cur;
3010 crl_cur = crl_cur->next;
3011
3012 memset( crl_prv, 0, sizeof( x509_crl ) );
3013 if( crl_prv != crl )
3014 free( crl_prv );
3015 }
3016 while( crl_cur != NULL );
3017}
3018
Paul Bakker40e46942009-01-03 21:51:57 +00003019#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00003020
Paul Bakker40e46942009-01-03 21:51:57 +00003021#include "polarssl/certs.h"
Paul Bakker5121ce52009-01-03 21:22:43 +00003022
3023/*
3024 * Checkup routine
3025 */
3026int x509_self_test( int verbose )
3027{
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00003028#if defined(POLARSSL_MD5_C)
Paul Bakker23986e52011-04-24 08:57:21 +00003029 int ret;
3030 int flags;
3031 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +00003032 x509_cert cacert;
3033 x509_cert clicert;
3034 rsa_context rsa;
Paul Bakker1b57b062011-01-06 15:48:19 +00003035 dhm_context dhm;
Paul Bakker5121ce52009-01-03 21:22:43 +00003036
3037 if( verbose != 0 )
3038 printf( " X.509 certificate load: " );
3039
3040 memset( &clicert, 0, sizeof( x509_cert ) );
3041
3042 ret = x509parse_crt( &clicert, (unsigned char *) test_cli_crt,
3043 strlen( test_cli_crt ) );
3044 if( ret != 0 )
3045 {
3046 if( verbose != 0 )
3047 printf( "failed\n" );
3048
3049 return( ret );
3050 }
3051
3052 memset( &cacert, 0, sizeof( x509_cert ) );
3053
3054 ret = x509parse_crt( &cacert, (unsigned char *) test_ca_crt,
3055 strlen( test_ca_crt ) );
3056 if( ret != 0 )
3057 {
3058 if( verbose != 0 )
3059 printf( "failed\n" );
3060
3061 return( ret );
3062 }
3063
3064 if( verbose != 0 )
3065 printf( "passed\n X.509 private key load: " );
3066
3067 i = strlen( test_ca_key );
3068 j = strlen( test_ca_pwd );
3069
Paul Bakker66b78b22011-03-25 14:22:50 +00003070 rsa_init( &rsa, RSA_PKCS_V15, 0 );
3071
Paul Bakker5121ce52009-01-03 21:22:43 +00003072 if( ( ret = x509parse_key( &rsa,
3073 (unsigned char *) test_ca_key, i,
3074 (unsigned char *) test_ca_pwd, j ) ) != 0 )
3075 {
3076 if( verbose != 0 )
3077 printf( "failed\n" );
3078
3079 return( ret );
3080 }
3081
3082 if( verbose != 0 )
3083 printf( "passed\n X.509 signature verify: ");
3084
Paul Bakker23986e52011-04-24 08:57:21 +00003085 ret = x509parse_verify( &clicert, &cacert, NULL, "PolarSSL Client 2", &flags, NULL, NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00003086 if( ret != 0 )
3087 {
Paul Bakker23986e52011-04-24 08:57:21 +00003088 printf("%02x", flags);
Paul Bakker5121ce52009-01-03 21:22:43 +00003089 if( verbose != 0 )
3090 printf( "failed\n" );
3091
3092 return( ret );
3093 }
3094
3095 if( verbose != 0 )
Paul Bakker1b57b062011-01-06 15:48:19 +00003096 printf( "passed\n X.509 DHM parameter load: " );
3097
3098 i = strlen( test_dhm_params );
3099 j = strlen( test_ca_pwd );
3100
3101 if( ( ret = x509parse_dhm( &dhm, (unsigned char *) test_dhm_params, i ) ) != 0 )
3102 {
3103 if( verbose != 0 )
3104 printf( "failed\n" );
3105
3106 return( ret );
3107 }
3108
3109 if( verbose != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003110 printf( "passed\n\n" );
3111
3112 x509_free( &cacert );
3113 x509_free( &clicert );
3114 rsa_free( &rsa );
Paul Bakker1b57b062011-01-06 15:48:19 +00003115 dhm_free( &dhm );
Paul Bakker5121ce52009-01-03 21:22:43 +00003116
3117 return( 0 );
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00003118#else
3119 ((void) verbose);
3120 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
3121#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00003122}
3123
3124#endif
3125
3126#endif