blob: ea9748c9faeecc4330b38af6cae93a46d434d2f5 [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"
42#include "polarssl/base64.h"
43#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 Bakker5121ce52009-01-03 21:22:43 +000050
51#include <string.h>
52#include <stdlib.h>
53#include <stdio.h>
54#include <time.h>
55
56/*
57 * ASN.1 DER decoding routines
58 */
59static int asn1_get_len( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +000060 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +000061 int *len )
62{
63 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +000064 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000065
66 if( ( **p & 0x80 ) == 0 )
67 *len = *(*p)++;
68 else
69 {
70 switch( **p & 0x7F )
71 {
72 case 1:
73 if( ( end - *p ) < 2 )
Paul Bakker40e46942009-01-03 21:51:57 +000074 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000075
76 *len = (*p)[1];
77 (*p) += 2;
78 break;
79
80 case 2:
81 if( ( end - *p ) < 3 )
Paul Bakker40e46942009-01-03 21:51:57 +000082 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000083
84 *len = ( (*p)[1] << 8 ) | (*p)[2];
85 (*p) += 3;
86 break;
87
88 default:
Paul Bakker40e46942009-01-03 21:51:57 +000089 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
Paul Bakker5121ce52009-01-03 21:22:43 +000090 break;
91 }
92 }
93
94 if( *len > (int) ( end - *p ) )
Paul Bakker40e46942009-01-03 21:51:57 +000095 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000096
97 return( 0 );
98}
99
100static int asn1_get_tag( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000101 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000102 int *len, int tag )
103{
104 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000105 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000106
107 if( **p != tag )
Paul Bakker40e46942009-01-03 21:51:57 +0000108 return( POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000109
110 (*p)++;
111
112 return( asn1_get_len( p, end, len ) );
113}
114
115static int asn1_get_bool( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000116 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000117 int *val )
118{
119 int ret, len;
120
121 if( ( ret = asn1_get_tag( p, end, &len, ASN1_BOOLEAN ) ) != 0 )
122 return( ret );
123
124 if( len != 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000125 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000126
127 *val = ( **p != 0 ) ? 1 : 0;
128 (*p)++;
129
130 return( 0 );
131}
132
133static int asn1_get_int( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000134 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000135 int *val )
136{
137 int ret, len;
138
139 if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
140 return( ret );
141
142 if( len > (int) sizeof( int ) || ( **p & 0x80 ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000143 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000144
145 *val = 0;
146
147 while( len-- > 0 )
148 {
149 *val = ( *val << 8 ) | **p;
150 (*p)++;
151 }
152
153 return( 0 );
154}
155
156static int asn1_get_mpi( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000157 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000158 mpi *X )
159{
160 int ret, len;
161
162 if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
163 return( ret );
164
165 ret = mpi_read_binary( X, *p, len );
166
167 *p += len;
168
169 return( ret );
170}
171
172/*
173 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
174 */
175static int x509_get_version( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000176 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000177 int *ver )
178{
179 int ret, len;
180
181 if( ( ret = asn1_get_tag( p, end, &len,
182 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) != 0 )
183 {
Paul Bakker40e46942009-01-03 21:51:57 +0000184 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker5121ce52009-01-03 21:22:43 +0000185 return( *ver = 0 );
186
187 return( ret );
188 }
189
190 end = *p + len;
191
192 if( ( ret = asn1_get_int( p, end, ver ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000193 return( POLARSSL_ERR_X509_CERT_INVALID_VERSION | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000194
195 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000196 return( POLARSSL_ERR_X509_CERT_INVALID_VERSION |
197 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000198
199 return( 0 );
200}
201
202/*
203 * CertificateSerialNumber ::= INTEGER
204 */
205static int x509_get_serial( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000206 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000207 x509_buf *serial )
208{
209 int ret;
210
211 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000212 return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL |
213 POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000214
215 if( **p != ( ASN1_CONTEXT_SPECIFIC | ASN1_PRIMITIVE | 2 ) &&
216 **p != ASN1_INTEGER )
Paul Bakker40e46942009-01-03 21:51:57 +0000217 return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL |
218 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000219
220 serial->tag = *(*p)++;
221
222 if( ( ret = asn1_get_len( p, end, &serial->len ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000223 return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000224
225 serial->p = *p;
226 *p += serial->len;
227
228 return( 0 );
229}
230
231/*
232 * AlgorithmIdentifier ::= SEQUENCE {
233 * algorithm OBJECT IDENTIFIER,
234 * parameters ANY DEFINED BY algorithm OPTIONAL }
235 */
236static int x509_get_alg( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000237 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000238 x509_buf *alg )
239{
240 int ret, len;
241
242 if( ( ret = asn1_get_tag( p, end, &len,
243 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000244 return( POLARSSL_ERR_X509_CERT_INVALID_ALG | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000245
246 end = *p + len;
247 alg->tag = **p;
248
249 if( ( ret = asn1_get_tag( p, end, &alg->len, ASN1_OID ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000250 return( POLARSSL_ERR_X509_CERT_INVALID_ALG | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000251
252 alg->p = *p;
253 *p += alg->len;
254
255 if( *p == end )
256 return( 0 );
257
258 /*
259 * assume the algorithm parameters must be NULL
260 */
261 if( ( ret = asn1_get_tag( p, end, &len, ASN1_NULL ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000262 return( POLARSSL_ERR_X509_CERT_INVALID_ALG | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000263
264 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000265 return( POLARSSL_ERR_X509_CERT_INVALID_ALG |
266 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000267
268 return( 0 );
269}
270
271/*
272 * RelativeDistinguishedName ::=
273 * SET OF AttributeTypeAndValue
274 *
275 * AttributeTypeAndValue ::= SEQUENCE {
276 * type AttributeType,
277 * value AttributeValue }
278 *
279 * AttributeType ::= OBJECT IDENTIFIER
280 *
281 * AttributeValue ::= ANY DEFINED BY AttributeType
282 */
283static int x509_get_name( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000284 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000285 x509_name *cur )
286{
287 int ret, len;
Paul Bakkerff60ee62010-03-16 21:09:09 +0000288 const unsigned char *end2;
Paul Bakker5121ce52009-01-03 21:22:43 +0000289 x509_buf *oid;
290 x509_buf *val;
291
292 if( ( ret = asn1_get_tag( p, end, &len,
293 ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000294 return( POLARSSL_ERR_X509_CERT_INVALID_NAME | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000295
296 end2 = end;
297 end = *p + len;
298
299 if( ( ret = asn1_get_tag( p, end, &len,
300 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000301 return( POLARSSL_ERR_X509_CERT_INVALID_NAME | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000302
303 if( *p + len != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000304 return( POLARSSL_ERR_X509_CERT_INVALID_NAME |
305 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000306
307 oid = &cur->oid;
308 oid->tag = **p;
309
310 if( ( ret = asn1_get_tag( p, end, &oid->len, ASN1_OID ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000311 return( POLARSSL_ERR_X509_CERT_INVALID_NAME | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000312
313 oid->p = *p;
314 *p += oid->len;
315
316 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000317 return( POLARSSL_ERR_X509_CERT_INVALID_NAME |
318 POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000319
320 if( **p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING &&
321 **p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING &&
322 **p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING )
Paul Bakker40e46942009-01-03 21:51:57 +0000323 return( POLARSSL_ERR_X509_CERT_INVALID_NAME |
324 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000325
326 val = &cur->val;
327 val->tag = *(*p)++;
328
329 if( ( ret = asn1_get_len( p, end, &val->len ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000330 return( POLARSSL_ERR_X509_CERT_INVALID_NAME | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000331
332 val->p = *p;
333 *p += val->len;
334
335 cur->next = NULL;
336
337 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000338 return( POLARSSL_ERR_X509_CERT_INVALID_NAME |
339 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000340
341 /*
342 * recurse until end of SEQUENCE is reached
343 */
344 if( *p == end2 )
345 return( 0 );
346
347 cur->next = (x509_name *) malloc(
348 sizeof( x509_name ) );
349
350 if( cur->next == NULL )
351 return( 1 );
352
353 return( x509_get_name( p, end2, cur->next ) );
354}
355
356/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000357 * Time ::= CHOICE {
358 * utcTime UTCTime,
359 * generalTime GeneralizedTime }
360 */
Paul Bakker91200182010-02-18 21:26:15 +0000361static int x509_get_time( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000362 const unsigned char *end,
Paul Bakkerd98030e2009-05-02 15:13:40 +0000363 x509_time *time )
364{
365 int ret, len;
366 char date[64];
Paul Bakker91200182010-02-18 21:26:15 +0000367 unsigned char tag;
Paul Bakkerd98030e2009-05-02 15:13:40 +0000368
Paul Bakker91200182010-02-18 21:26:15 +0000369 if( ( end - *p ) < 1 )
370 return( POLARSSL_ERR_X509_CERT_INVALID_DATE | POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakkerd98030e2009-05-02 15:13:40 +0000371
Paul Bakker91200182010-02-18 21:26:15 +0000372 tag = **p;
Paul Bakkerd98030e2009-05-02 15:13:40 +0000373
Paul Bakker91200182010-02-18 21:26:15 +0000374 if ( tag == ASN1_UTC_TIME )
375 {
376 (*p)++;
377 ret = asn1_get_len( p, end, &len );
378
379 if( ret != 0 )
380 return( POLARSSL_ERR_X509_CERT_INVALID_DATE | ret );
Paul Bakkerd98030e2009-05-02 15:13:40 +0000381
Paul Bakker91200182010-02-18 21:26:15 +0000382 memset( date, 0, sizeof( date ) );
383 memcpy( date, *p, ( len < (int) sizeof( date ) - 1 ) ?
384 len : (int) sizeof( date ) - 1 );
Paul Bakkerd98030e2009-05-02 15:13:40 +0000385
Paul Bakker91200182010-02-18 21:26:15 +0000386 if( sscanf( date, "%2d%2d%2d%2d%2d%2d",
387 &time->year, &time->mon, &time->day,
388 &time->hour, &time->min, &time->sec ) < 5 )
389 return( POLARSSL_ERR_X509_CERT_INVALID_DATE );
Paul Bakkerd98030e2009-05-02 15:13:40 +0000390
Paul Bakker91200182010-02-18 21:26:15 +0000391 time->year += 100 * ( time->year < 90 );
392 time->year += 1900;
393
394 *p += len;
395
396 return( 0 );
397 }
398 else if ( tag == ASN1_GENERALIZED_TIME )
399 {
400 (*p)++;
401 ret = asn1_get_len( p, end, &len );
402
403 if( ret != 0 )
404 return( POLARSSL_ERR_X509_CERT_INVALID_DATE | ret );
405
406 memset( date, 0, sizeof( date ) );
407 memcpy( date, *p, ( len < (int) sizeof( date ) - 1 ) ?
408 len : (int) sizeof( date ) - 1 );
409
410 if( sscanf( date, "%4d%2d%2d%2d%2d%2d",
411 &time->year, &time->mon, &time->day,
412 &time->hour, &time->min, &time->sec ) < 5 )
413 return( POLARSSL_ERR_X509_CERT_INVALID_DATE );
414
415 *p += len;
416
417 return( 0 );
418 }
419 else
420 return( POLARSSL_ERR_X509_CERT_INVALID_DATE | POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakkerd98030e2009-05-02 15:13:40 +0000421}
422
423
424/*
425 * Validity ::= SEQUENCE {
426 * notBefore Time,
427 * notAfter Time }
428 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000429static int x509_get_dates( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000430 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000431 x509_time *from,
432 x509_time *to )
433{
434 int ret, len;
Paul Bakker5121ce52009-01-03 21:22:43 +0000435
436 if( ( ret = asn1_get_tag( p, end, &len,
437 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000438 return( POLARSSL_ERR_X509_CERT_INVALID_DATE | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000439
440 end = *p + len;
441
Paul Bakker91200182010-02-18 21:26:15 +0000442 if( ( ret = x509_get_time( p, end, from ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +0000443 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000444
Paul Bakker91200182010-02-18 21:26:15 +0000445 if( ( ret = x509_get_time( p, end, to ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +0000446 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000447
448 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000449 return( POLARSSL_ERR_X509_CERT_INVALID_DATE |
450 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000451
452 return( 0 );
453}
454
455/*
456 * SubjectPublicKeyInfo ::= SEQUENCE {
457 * algorithm AlgorithmIdentifier,
458 * subjectPublicKey BIT STRING }
459 */
460static int x509_get_pubkey( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000461 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000462 x509_buf *pk_alg_oid,
463 mpi *N, mpi *E )
464{
465 int ret, len;
466 unsigned char *end2;
467
468 if( ( ret = x509_get_alg( p, end, pk_alg_oid ) ) != 0 )
469 return( ret );
470
471 /*
472 * only RSA public keys handled at this time
473 */
474 if( pk_alg_oid->len != 9 ||
475 memcmp( pk_alg_oid->p, OID_PKCS1_RSA, 9 ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000476 return( POLARSSL_ERR_X509_CERT_UNKNOWN_PK_ALG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000477
478 if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000479 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000480
481 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000482 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY |
483 POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000484
485 end2 = *p + len;
486
487 if( *(*p)++ != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000488 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY );
Paul Bakker5121ce52009-01-03 21:22:43 +0000489
490 /*
491 * RSAPublicKey ::= SEQUENCE {
492 * modulus INTEGER, -- n
493 * publicExponent INTEGER -- e
494 * }
495 */
496 if( ( ret = asn1_get_tag( p, end2, &len,
497 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000498 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000499
500 if( *p + len != end2 )
Paul Bakker40e46942009-01-03 21:51:57 +0000501 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY |
502 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000503
504 if( ( ret = asn1_get_mpi( p, end2, N ) ) != 0 ||
505 ( ret = asn1_get_mpi( p, end2, E ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000506 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000507
508 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000509 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY |
510 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000511
512 return( 0 );
513}
514
515static int x509_get_sig( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000516 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000517 x509_buf *sig )
518{
519 int ret, len;
520
521 sig->tag = **p;
522
523 if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000524 return( POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000525
526 if( --len < 1 || *(*p)++ != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000527 return( POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000528
529 sig->len = len;
530 sig->p = *p;
531
532 *p += len;
533
534 return( 0 );
535}
536
537/*
538 * X.509 v2/v3 unique identifier (not parsed)
539 */
540static int x509_get_uid( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000541 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000542 x509_buf *uid, int n )
543{
544 int ret;
545
546 if( *p == end )
547 return( 0 );
548
549 uid->tag = **p;
550
551 if( ( ret = asn1_get_tag( p, end, &uid->len,
552 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | n ) ) != 0 )
553 {
Paul Bakker40e46942009-01-03 21:51:57 +0000554 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker5121ce52009-01-03 21:22:43 +0000555 return( 0 );
556
557 return( ret );
558 }
559
560 uid->p = *p;
561 *p += uid->len;
562
563 return( 0 );
564}
565
566/*
Paul Bakkerd98030e2009-05-02 15:13:40 +0000567 * X.509 Extensions (No parsing of extensions, pointer should
568 * be either manually updated or extensions should be parsed!
Paul Bakker5121ce52009-01-03 21:22:43 +0000569 */
570static int x509_get_ext( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000571 const unsigned char *end,
Paul Bakkerd98030e2009-05-02 15:13:40 +0000572 x509_buf *ext )
Paul Bakker5121ce52009-01-03 21:22:43 +0000573{
574 int ret, len;
Paul Bakker5121ce52009-01-03 21:22:43 +0000575
576 if( *p == end )
577 return( 0 );
578
579 ext->tag = **p;
Paul Bakkerff60ee62010-03-16 21:09:09 +0000580
Paul Bakker5121ce52009-01-03 21:22:43 +0000581 if( ( ret = asn1_get_tag( p, end, &ext->len,
582 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000583 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000584
585 ext->p = *p;
586 end = *p + ext->len;
587
588 /*
589 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
590 *
591 * Extension ::= SEQUENCE {
592 * extnID OBJECT IDENTIFIER,
593 * critical BOOLEAN DEFAULT FALSE,
594 * extnValue OCTET STRING }
595 */
596 if( ( ret = asn1_get_tag( p, end, &len,
597 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000598 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000599
600 if( end != *p + len )
Paul Bakker40e46942009-01-03 21:51:57 +0000601 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
602 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000603
Paul Bakkerd98030e2009-05-02 15:13:40 +0000604 return( 0 );
605}
606
607/*
608 * X.509 CRL v2 extensions (no extensions parsed yet.)
609 */
610static int x509_get_crl_ext( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000611 const unsigned char *end,
612 x509_buf *ext )
Paul Bakkerd98030e2009-05-02 15:13:40 +0000613{
614 int ret, len;
615
616 if( ( ret = x509_get_ext( p, end, ext ) ) != 0 )
617 {
618 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
619 return( 0 );
620
621 return( ret );
622 }
623
624 while( *p < end )
625 {
626 if( ( ret = asn1_get_tag( p, end, &len,
627 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
628 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
629
630 *p += len;
631 }
632
633 if( *p != end )
634 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
635 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
636
637 return( 0 );
638}
639
640/*
641 * X.509 v3 extensions (only BasicConstraints are parsed)
642 */
643static int x509_get_crt_ext( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000644 const unsigned char *end,
645 x509_buf *ext,
646 int *ca_istrue,
647 int *max_pathlen )
Paul Bakkerd98030e2009-05-02 15:13:40 +0000648{
649 int ret, len;
650 int is_critical = 1;
651 int is_cacert = 0;
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000652 unsigned char *end_ext_data, *end_ext_octet;
Paul Bakkerd98030e2009-05-02 15:13:40 +0000653
654 if( ( ret = x509_get_ext( p, end, ext ) ) != 0 )
655 {
656 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
657 return( 0 );
658
659 return( ret );
660 }
661
Paul Bakker5121ce52009-01-03 21:22:43 +0000662 while( *p < end )
663 {
664 if( ( ret = asn1_get_tag( p, end, &len,
665 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000666 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000667
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000668 end_ext_data = *p + len;
669
Paul Bakker5121ce52009-01-03 21:22:43 +0000670 if( memcmp( *p, "\x06\x03\x55\x1D\x13", 5 ) != 0 )
671 {
672 *p += len;
673 continue;
674 }
675
676 *p += 5;
677
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000678 if( ( ret = asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 &&
Paul Bakker40e46942009-01-03 21:51:57 +0000679 ( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) )
680 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000681
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000682 if( ( ret = asn1_get_tag( p, end_ext_data, &len,
Paul Bakker5121ce52009-01-03 21:22:43 +0000683 ASN1_OCTET_STRING ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000684 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000685
686 /*
687 * BasicConstraints ::= SEQUENCE {
688 * cA BOOLEAN DEFAULT FALSE,
689 * pathLenConstraint INTEGER (0..MAX) OPTIONAL }
690 */
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000691 end_ext_octet = *p + len;
Paul Bakkerff60ee62010-03-16 21:09:09 +0000692
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000693 if( end_ext_octet != end_ext_data )
694 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
695 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000696
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000697 if( ( ret = asn1_get_tag( p, end_ext_octet, &len,
Paul Bakker5121ce52009-01-03 21:22:43 +0000698 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000699 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000700
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000701 if( *p == end_ext_octet )
Paul Bakker5121ce52009-01-03 21:22:43 +0000702 continue;
703
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000704 if( ( ret = asn1_get_bool( p, end_ext_octet, &is_cacert ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000705 {
Paul Bakker40e46942009-01-03 21:51:57 +0000706 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000707 ret = asn1_get_int( p, end_ext_octet, &is_cacert );
Paul Bakker5121ce52009-01-03 21:22:43 +0000708
709 if( ret != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000710 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000711
712 if( is_cacert != 0 )
713 is_cacert = 1;
714 }
715
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000716 if( *p == end_ext_octet )
Paul Bakker5121ce52009-01-03 21:22:43 +0000717 continue;
718
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000719 if( ( ret = asn1_get_int( p, end_ext_octet, max_pathlen ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000720 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000721
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000722 if( *p != end_ext_octet )
Paul Bakker40e46942009-01-03 21:51:57 +0000723 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
724 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000725
726 max_pathlen++;
727 }
728
729 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000730 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
731 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000732
733 *ca_istrue = is_critical & is_cacert;
734
735 return( 0 );
736}
737
738/*
Paul Bakkerd98030e2009-05-02 15:13:40 +0000739 * X.509 CRL Entries
740 */
741static int x509_get_entries( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000742 const unsigned char *end,
Paul Bakkerd98030e2009-05-02 15:13:40 +0000743 x509_crl_entry *entry )
744{
Paul Bakker9be19372009-07-27 20:21:53 +0000745 int ret, entry_len;
Paul Bakkerd98030e2009-05-02 15:13:40 +0000746 x509_crl_entry *cur_entry = entry;
747
748 if( *p == end )
749 return( 0 );
750
Paul Bakker9be19372009-07-27 20:21:53 +0000751 if( ( ret = asn1_get_tag( p, end, &entry_len,
Paul Bakkerd98030e2009-05-02 15:13:40 +0000752 ASN1_SEQUENCE | ASN1_CONSTRUCTED ) ) != 0 )
753 {
754 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
755 return( 0 );
756
757 return( ret );
758 }
759
Paul Bakker9be19372009-07-27 20:21:53 +0000760 end = *p + entry_len;
Paul Bakkerd98030e2009-05-02 15:13:40 +0000761
762 while( *p < end )
763 {
764 int len2;
765
766 if( ( ret = asn1_get_tag( p, end, &len2,
767 ASN1_SEQUENCE | ASN1_CONSTRUCTED ) ) != 0 )
768 {
Paul Bakkerd98030e2009-05-02 15:13:40 +0000769 return( ret );
770 }
771
Paul Bakker9be19372009-07-27 20:21:53 +0000772 cur_entry->raw.tag = **p;
773 cur_entry->raw.p = *p;
774 cur_entry->raw.len = len2;
775
Paul Bakkerd98030e2009-05-02 15:13:40 +0000776 if( ( ret = x509_get_serial( p, end, &cur_entry->serial ) ) != 0 )
777 return( ret );
778
Paul Bakker91200182010-02-18 21:26:15 +0000779 if( ( ret = x509_get_time( p, end, &cur_entry->revocation_date ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +0000780 return( ret );
781
782 if( ( ret = x509_get_crl_ext( p, end, &cur_entry->entry_ext ) ) != 0 )
783 return( ret );
784
785 if ( *p < end ) {
786 cur_entry->next = malloc( sizeof( x509_crl_entry ) );
787 cur_entry = cur_entry->next;
788 memset( cur_entry, 0, sizeof( x509_crl_entry ) );
789 }
790 }
791
792 return( 0 );
793}
794
Paul Bakker27d66162010-03-17 06:56:01 +0000795static int x509_get_sig_alg( const x509_buf *sig_oid, int *sig_alg )
796{
797 if( sig_oid->len == 9 &&
798 memcmp( sig_oid->p, OID_PKCS1, 8 ) == 0 )
799 {
800 if( sig_oid->p[8] >= 2 && sig_oid->p[8] <= 5 )
801 {
802 *sig_alg = sig_oid->p[8];
803 return( 0 );
804 }
805
806 if ( sig_oid->p[8] >= 11 && sig_oid->p[8] <= 14 )
807 {
808 *sig_alg = sig_oid->p[8];
809 return( 0 );
810 }
811
812 return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
813 }
814
815 return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
816}
817
Paul Bakkerd98030e2009-05-02 15:13:40 +0000818/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000819 * Parse one or more certificates and add them to the chained list
820 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000821int x509parse_crt( x509_cert *chain, const unsigned char *buf, int buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000822{
823 int ret, len;
Paul Bakkerff60ee62010-03-16 21:09:09 +0000824 const unsigned char *s1, *s2;
Paul Bakker5121ce52009-01-03 21:22:43 +0000825 unsigned char *p, *end;
826 x509_cert *crt;
827
828 crt = chain;
829
Paul Bakker320a4b52009-03-28 18:52:39 +0000830 /*
831 * Check for valid input
832 */
833 if( crt == NULL || buf == NULL )
834 return( 1 );
835
Paul Bakkere9581d62009-03-28 20:29:25 +0000836 while( crt->version != 0 && crt->next != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000837 crt = crt->next;
838
839 /*
Paul Bakker320a4b52009-03-28 18:52:39 +0000840 * Add new certificate on the end of the chain if needed.
841 */
Paul Bakkere9581d62009-03-28 20:29:25 +0000842 if ( crt->version != 0 && crt->next == NULL)
Paul Bakker320a4b52009-03-28 18:52:39 +0000843 {
844 crt->next = (x509_cert *) malloc( sizeof( x509_cert ) );
845
Paul Bakker7d06ad22009-05-02 15:53:56 +0000846 if( crt->next == NULL )
847 {
Paul Bakker320a4b52009-03-28 18:52:39 +0000848 x509_free( crt );
Paul Bakker7d06ad22009-05-02 15:53:56 +0000849 return( 1 );
850 }
Paul Bakker320a4b52009-03-28 18:52:39 +0000851
Paul Bakker7d06ad22009-05-02 15:53:56 +0000852 crt = crt->next;
853 memset( crt, 0, sizeof( x509_cert ) );
Paul Bakker320a4b52009-03-28 18:52:39 +0000854 }
855
856 /*
Paul Bakker5121ce52009-01-03 21:22:43 +0000857 * check if the certificate is encoded in base64
858 */
859 s1 = (unsigned char *) strstr( (char *) buf,
860 "-----BEGIN CERTIFICATE-----" );
861
862 if( s1 != NULL )
863 {
864 s2 = (unsigned char *) strstr( (char *) buf,
865 "-----END CERTIFICATE-----" );
866
867 if( s2 == NULL || s2 <= s1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000868 return( POLARSSL_ERR_X509_CERT_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +0000869
870 s1 += 27;
871 if( *s1 == '\r' ) s1++;
872 if( *s1 == '\n' ) s1++;
Paul Bakker40e46942009-01-03 21:51:57 +0000873 else return( POLARSSL_ERR_X509_CERT_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +0000874
875 /*
876 * get the DER data length and decode the buffer
877 */
878 len = 0;
879 ret = base64_decode( NULL, &len, s1, s2 - s1 );
880
Paul Bakker40e46942009-01-03 21:51:57 +0000881 if( ret == POLARSSL_ERR_BASE64_INVALID_CHARACTER )
882 return( POLARSSL_ERR_X509_CERT_INVALID_PEM | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000883
884 if( ( p = (unsigned char *) malloc( len ) ) == NULL )
885 return( 1 );
886
887 if( ( ret = base64_decode( p, &len, s1, s2 - s1 ) ) != 0 )
888 {
889 free( p );
Paul Bakker40e46942009-01-03 21:51:57 +0000890 return( POLARSSL_ERR_X509_CERT_INVALID_PEM | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000891 }
892
893 /*
894 * update the buffer size and offset
895 */
896 s2 += 25;
897 if( *s2 == '\r' ) s2++;
898 if( *s2 == '\n' ) s2++;
899 else
900 {
901 free( p );
Paul Bakker40e46942009-01-03 21:51:57 +0000902 return( POLARSSL_ERR_X509_CERT_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +0000903 }
904
905 buflen -= s2 - buf;
906 buf = s2;
907 }
908 else
909 {
910 /*
911 * nope, copy the raw DER data
912 */
913 p = (unsigned char *) malloc( len = buflen );
914
915 if( p == NULL )
916 return( 1 );
917
918 memcpy( p, buf, buflen );
919
920 buflen = 0;
921 }
922
923 crt->raw.p = p;
924 crt->raw.len = len;
925 end = p + len;
926
927 /*
928 * Certificate ::= SEQUENCE {
929 * tbsCertificate TBSCertificate,
930 * signatureAlgorithm AlgorithmIdentifier,
931 * signatureValue BIT STRING }
932 */
933 if( ( ret = asn1_get_tag( &p, end, &len,
934 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
935 {
Paul Bakker7d06ad22009-05-02 15:53:56 +0000936 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000937 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT );
Paul Bakker5121ce52009-01-03 21:22:43 +0000938 }
939
940 if( len != (int) ( end - p ) )
941 {
Paul Bakker7d06ad22009-05-02 15:53:56 +0000942 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000943 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT |
944 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000945 }
946
947 /*
948 * TBSCertificate ::= SEQUENCE {
949 */
950 crt->tbs.p = p;
951
952 if( ( ret = asn1_get_tag( &p, end, &len,
953 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
954 {
Paul Bakker7d06ad22009-05-02 15:53:56 +0000955 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000956 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000957 }
958
959 end = p + len;
960 crt->tbs.len = end - crt->tbs.p;
961
962 /*
963 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
964 *
965 * CertificateSerialNumber ::= INTEGER
966 *
967 * signature AlgorithmIdentifier
968 */
969 if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 ||
970 ( ret = x509_get_serial( &p, end, &crt->serial ) ) != 0 ||
971 ( ret = x509_get_alg( &p, end, &crt->sig_oid1 ) ) != 0 )
972 {
Paul Bakker7d06ad22009-05-02 15:53:56 +0000973 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +0000974 return( ret );
975 }
976
977 crt->version++;
978
979 if( crt->version > 3 )
980 {
Paul Bakker7d06ad22009-05-02 15:53:56 +0000981 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000982 return( POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION );
Paul Bakker5121ce52009-01-03 21:22:43 +0000983 }
984
Paul Bakker27d66162010-03-17 06:56:01 +0000985 if( ( ret = x509_get_sig_alg( &crt->sig_oid1, &crt->sig_alg ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000986 {
Paul Bakker7d06ad22009-05-02 15:53:56 +0000987 x509_free( crt );
Paul Bakker27d66162010-03-17 06:56:01 +0000988 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000989 }
990
991 /*
992 * issuer Name
993 */
994 crt->issuer_raw.p = p;
995
996 if( ( ret = asn1_get_tag( &p, end, &len,
997 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
998 {
Paul Bakker7d06ad22009-05-02 15:53:56 +0000999 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +00001000 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001001 }
1002
1003 if( ( ret = x509_get_name( &p, p + len, &crt->issuer ) ) != 0 )
1004 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001005 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001006 return( ret );
1007 }
1008
1009 crt->issuer_raw.len = p - crt->issuer_raw.p;
1010
1011 /*
1012 * Validity ::= SEQUENCE {
1013 * notBefore Time,
1014 * notAfter Time }
1015 *
1016 */
1017 if( ( ret = x509_get_dates( &p, end, &crt->valid_from,
1018 &crt->valid_to ) ) != 0 )
1019 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001020 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001021 return( ret );
1022 }
1023
1024 /*
1025 * subject Name
1026 */
1027 crt->subject_raw.p = p;
1028
1029 if( ( ret = asn1_get_tag( &p, end, &len,
1030 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1031 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001032 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +00001033 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001034 }
1035
1036 if( ( ret = x509_get_name( &p, p + len, &crt->subject ) ) != 0 )
1037 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001038 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001039 return( ret );
1040 }
1041
1042 crt->subject_raw.len = p - crt->subject_raw.p;
1043
1044 /*
1045 * SubjectPublicKeyInfo ::= SEQUENCE
1046 * algorithm AlgorithmIdentifier,
1047 * subjectPublicKey BIT STRING }
1048 */
1049 if( ( ret = asn1_get_tag( &p, end, &len,
1050 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1051 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001052 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +00001053 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001054 }
1055
1056 if( ( ret = x509_get_pubkey( &p, p + len, &crt->pk_oid,
1057 &crt->rsa.N, &crt->rsa.E ) ) != 0 )
1058 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001059 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001060 return( ret );
1061 }
1062
1063 if( ( ret = rsa_check_pubkey( &crt->rsa ) ) != 0 )
1064 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001065 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001066 return( ret );
1067 }
1068
1069 crt->rsa.len = mpi_size( &crt->rsa.N );
1070
1071 /*
1072 * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
1073 * -- If present, version shall be v2 or v3
1074 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
1075 * -- If present, version shall be v2 or v3
1076 * extensions [3] EXPLICIT Extensions OPTIONAL
1077 * -- If present, version shall be v3
1078 */
1079 if( crt->version == 2 || crt->version == 3 )
1080 {
1081 ret = x509_get_uid( &p, end, &crt->issuer_id, 1 );
1082 if( ret != 0 )
1083 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001084 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001085 return( ret );
1086 }
1087 }
1088
1089 if( crt->version == 2 || crt->version == 3 )
1090 {
1091 ret = x509_get_uid( &p, end, &crt->subject_id, 2 );
1092 if( ret != 0 )
1093 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001094 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001095 return( ret );
1096 }
1097 }
1098
1099 if( crt->version == 3 )
1100 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00001101 ret = x509_get_crt_ext( &p, end, &crt->v3_ext,
Paul Bakker5121ce52009-01-03 21:22:43 +00001102 &crt->ca_istrue, &crt->max_pathlen );
1103 if( ret != 0 )
1104 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001105 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001106 return( ret );
1107 }
1108 }
1109
1110 if( p != end )
1111 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001112 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +00001113 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT |
1114 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001115 }
1116
1117 end = crt->raw.p + crt->raw.len;
1118
1119 /*
1120 * signatureAlgorithm AlgorithmIdentifier,
1121 * signatureValue BIT STRING
1122 */
1123 if( ( ret = x509_get_alg( &p, end, &crt->sig_oid2 ) ) != 0 )
1124 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001125 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001126 return( ret );
1127 }
1128
Paul Bakker320a4b52009-03-28 18:52:39 +00001129 if( memcmp( crt->sig_oid1.p, crt->sig_oid2.p, crt->sig_oid1.len ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001130 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001131 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +00001132 return( POLARSSL_ERR_X509_CERT_SIG_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001133 }
1134
1135 if( ( ret = x509_get_sig( &p, end, &crt->sig ) ) != 0 )
1136 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001137 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001138 return( ret );
1139 }
1140
1141 if( p != end )
1142 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001143 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +00001144 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT |
1145 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001146 }
1147
Paul Bakker5121ce52009-01-03 21:22:43 +00001148 if( buflen > 0 )
Paul Bakker320a4b52009-03-28 18:52:39 +00001149 {
1150 crt->next = (x509_cert *) malloc( sizeof( x509_cert ) );
1151
Paul Bakker7d06ad22009-05-02 15:53:56 +00001152 if( crt->next == NULL )
1153 {
Paul Bakker320a4b52009-03-28 18:52:39 +00001154 x509_free( crt );
Paul Bakker7d06ad22009-05-02 15:53:56 +00001155 return( 1 );
1156 }
Paul Bakker320a4b52009-03-28 18:52:39 +00001157
Paul Bakker7d06ad22009-05-02 15:53:56 +00001158 crt = crt->next;
1159 memset( crt, 0, sizeof( x509_cert ) );
Paul Bakker320a4b52009-03-28 18:52:39 +00001160
Paul Bakker5121ce52009-01-03 21:22:43 +00001161 return( x509parse_crt( crt, buf, buflen ) );
Paul Bakker320a4b52009-03-28 18:52:39 +00001162 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001163
1164 return( 0 );
1165}
1166
1167/*
Paul Bakkerd98030e2009-05-02 15:13:40 +00001168 * Parse one or more CRLs and add them to the chained list
1169 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001170int x509parse_crl( x509_crl *chain, const unsigned char *buf, int buflen )
Paul Bakkerd98030e2009-05-02 15:13:40 +00001171{
1172 int ret, len;
1173 unsigned char *s1, *s2;
1174 unsigned char *p, *end;
1175 x509_crl *crl;
1176
1177 crl = chain;
1178
1179 /*
1180 * Check for valid input
1181 */
1182 if( crl == NULL || buf == NULL )
1183 return( 1 );
1184
1185 while( crl->version != 0 && crl->next != NULL )
1186 crl = crl->next;
1187
1188 /*
1189 * Add new CRL on the end of the chain if needed.
1190 */
1191 if ( crl->version != 0 && crl->next == NULL)
1192 {
1193 crl->next = (x509_crl *) malloc( sizeof( x509_crl ) );
1194
Paul Bakker7d06ad22009-05-02 15:53:56 +00001195 if( crl->next == NULL )
1196 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00001197 x509_crl_free( crl );
Paul Bakker7d06ad22009-05-02 15:53:56 +00001198 return( 1 );
1199 }
Paul Bakkerd98030e2009-05-02 15:13:40 +00001200
Paul Bakker7d06ad22009-05-02 15:53:56 +00001201 crl = crl->next;
1202 memset( crl, 0, sizeof( x509_crl ) );
Paul Bakkerd98030e2009-05-02 15:13:40 +00001203 }
1204
1205 /*
1206 * check if the CRL is encoded in base64
1207 */
1208 s1 = (unsigned char *) strstr( (char *) buf,
1209 "-----BEGIN X509 CRL-----" );
1210
1211 if( s1 != NULL )
1212 {
1213 s2 = (unsigned char *) strstr( (char *) buf,
1214 "-----END X509 CRL-----" );
1215
1216 if( s2 == NULL || s2 <= s1 )
1217 return( POLARSSL_ERR_X509_CERT_INVALID_PEM );
1218
1219 s1 += 24;
1220 if( *s1 == '\r' ) s1++;
1221 if( *s1 == '\n' ) s1++;
1222 else return( POLARSSL_ERR_X509_CERT_INVALID_PEM );
1223
1224 /*
1225 * get the DER data length and decode the buffer
1226 */
1227 len = 0;
1228 ret = base64_decode( NULL, &len, s1, s2 - s1 );
1229
1230 if( ret == POLARSSL_ERR_BASE64_INVALID_CHARACTER )
1231 return( POLARSSL_ERR_X509_CERT_INVALID_PEM | ret );
1232
1233 if( ( p = (unsigned char *) malloc( len ) ) == NULL )
1234 return( 1 );
1235
1236 if( ( ret = base64_decode( p, &len, s1, s2 - s1 ) ) != 0 )
1237 {
1238 free( p );
1239 return( POLARSSL_ERR_X509_CERT_INVALID_PEM | ret );
1240 }
1241
1242 /*
1243 * update the buffer size and offset
1244 */
1245 s2 += 22;
1246 if( *s2 == '\r' ) s2++;
1247 if( *s2 == '\n' ) s2++;
1248 else
1249 {
1250 free( p );
1251 return( POLARSSL_ERR_X509_CERT_INVALID_PEM );
1252 }
1253
1254 buflen -= s2 - buf;
1255 buf = s2;
1256 }
1257 else
1258 {
1259 /*
1260 * nope, copy the raw DER data
1261 */
1262 p = (unsigned char *) malloc( len = buflen );
1263
1264 if( p == NULL )
1265 return( 1 );
1266
1267 memcpy( p, buf, buflen );
1268
1269 buflen = 0;
1270 }
1271
1272 crl->raw.p = p;
1273 crl->raw.len = len;
1274 end = p + len;
1275
1276 /*
1277 * CertificateList ::= SEQUENCE {
1278 * tbsCertList TBSCertList,
1279 * signatureAlgorithm AlgorithmIdentifier,
1280 * signatureValue BIT STRING }
1281 */
1282 if( ( ret = asn1_get_tag( &p, end, &len,
1283 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1284 {
1285 x509_crl_free( crl );
1286 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT );
1287 }
1288
1289 if( len != (int) ( end - p ) )
1290 {
1291 x509_crl_free( crl );
1292 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT |
1293 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
1294 }
1295
1296 /*
1297 * TBSCertList ::= SEQUENCE {
1298 */
1299 crl->tbs.p = p;
1300
1301 if( ( ret = asn1_get_tag( &p, end, &len,
1302 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1303 {
1304 x509_crl_free( crl );
1305 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
1306 }
1307
1308 end = p + len;
1309 crl->tbs.len = end - crl->tbs.p;
1310
1311 /*
1312 * Version ::= INTEGER OPTIONAL { v1(0), v2(1) }
1313 * -- if present, MUST be v2
1314 *
1315 * signature AlgorithmIdentifier
1316 */
1317 if( ( ret = x509_get_version( &p, end, &crl->version ) ) != 0 ||
1318 ( ret = x509_get_alg( &p, end, &crl->sig_oid1 ) ) != 0 )
1319 {
1320 x509_crl_free( crl );
1321 return( ret );
1322 }
1323
1324 crl->version++;
1325
1326 if( crl->version > 2 )
1327 {
1328 x509_crl_free( crl );
1329 return( POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION );
1330 }
1331
Paul Bakker27d66162010-03-17 06:56:01 +00001332 if( ( ret = x509_get_sig_alg( &crl->sig_oid1, &crl->sig_alg ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +00001333 {
1334 x509_crl_free( crl );
1335 return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
1336 }
1337
1338 /*
1339 * issuer Name
1340 */
1341 crl->issuer_raw.p = p;
1342
1343 if( ( ret = asn1_get_tag( &p, end, &len,
1344 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1345 {
1346 x509_crl_free( crl );
1347 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
1348 }
1349
1350 if( ( ret = x509_get_name( &p, p + len, &crl->issuer ) ) != 0 )
1351 {
1352 x509_crl_free( crl );
1353 return( ret );
1354 }
1355
1356 crl->issuer_raw.len = p - crl->issuer_raw.p;
1357
1358 /*
1359 * thisUpdate Time
1360 * nextUpdate Time OPTIONAL
1361 */
Paul Bakker91200182010-02-18 21:26:15 +00001362 if( ( ret = x509_get_time( &p, end, &crl->this_update ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +00001363 {
1364 x509_crl_free( crl );
1365 return( ret );
1366 }
1367
Paul Bakker91200182010-02-18 21:26:15 +00001368 if( ( ret = x509_get_time( &p, end, &crl->next_update ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +00001369 {
Paul Bakker635f4b42009-07-20 20:34:41 +00001370 if ( ret != ( POLARSSL_ERR_X509_CERT_INVALID_DATE |
Paul Bakker9be19372009-07-27 20:21:53 +00001371 POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) &&
1372 ret != ( POLARSSL_ERR_X509_CERT_INVALID_DATE |
1373 POLARSSL_ERR_ASN1_OUT_OF_DATA ) )
Paul Bakker635f4b42009-07-20 20:34:41 +00001374 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00001375 x509_crl_free( crl );
1376 return( ret );
1377 }
1378 }
1379
1380 /*
1381 * revokedCertificates SEQUENCE OF SEQUENCE {
1382 * userCertificate CertificateSerialNumber,
1383 * revocationDate Time,
1384 * crlEntryExtensions Extensions OPTIONAL
1385 * -- if present, MUST be v2
1386 * } OPTIONAL
1387 */
1388 if( ( ret = x509_get_entries( &p, end, &crl->entry ) ) != 0 )
1389 {
1390 x509_crl_free( crl );
1391 return( ret );
1392 }
1393
1394 /*
1395 * crlExtensions EXPLICIT Extensions OPTIONAL
1396 * -- if present, MUST be v2
1397 */
1398 if( crl->version == 2 )
1399 {
1400 ret = x509_get_crl_ext( &p, end, &crl->crl_ext );
1401
1402 if( ret != 0 )
1403 {
1404 x509_crl_free( crl );
1405 return( ret );
1406 }
1407 }
1408
1409 if( p != end )
1410 {
1411 x509_crl_free( crl );
1412 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT |
1413 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
1414 }
1415
1416 end = crl->raw.p + crl->raw.len;
1417
1418 /*
1419 * signatureAlgorithm AlgorithmIdentifier,
1420 * signatureValue BIT STRING
1421 */
1422 if( ( ret = x509_get_alg( &p, end, &crl->sig_oid2 ) ) != 0 )
1423 {
1424 x509_crl_free( crl );
1425 return( ret );
1426 }
1427
1428 if( memcmp( crl->sig_oid1.p, crl->sig_oid2.p, crl->sig_oid1.len ) != 0 )
1429 {
1430 x509_crl_free( crl );
1431 return( POLARSSL_ERR_X509_CERT_SIG_MISMATCH );
1432 }
1433
1434 if( ( ret = x509_get_sig( &p, end, &crl->sig ) ) != 0 )
1435 {
1436 x509_crl_free( crl );
1437 return( ret );
1438 }
1439
1440 if( p != end )
1441 {
1442 x509_crl_free( crl );
1443 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT |
1444 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
1445 }
1446
1447 if( buflen > 0 )
1448 {
1449 crl->next = (x509_crl *) malloc( sizeof( x509_crl ) );
1450
Paul Bakker7d06ad22009-05-02 15:53:56 +00001451 if( crl->next == NULL )
1452 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00001453 x509_crl_free( crl );
Paul Bakker7d06ad22009-05-02 15:53:56 +00001454 return( 1 );
1455 }
Paul Bakkerd98030e2009-05-02 15:13:40 +00001456
Paul Bakker7d06ad22009-05-02 15:53:56 +00001457 crl = crl->next;
1458 memset( crl, 0, sizeof( x509_crl ) );
Paul Bakkerd98030e2009-05-02 15:13:40 +00001459
1460 return( x509parse_crl( crl, buf, buflen ) );
1461 }
1462
1463 return( 0 );
1464}
1465
1466/*
Paul Bakker2b245eb2009-04-19 18:44:26 +00001467 * Load all data from a file into a given buffer.
1468 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001469int load_file( const char *path, unsigned char **buf, size_t *n )
Paul Bakker2b245eb2009-04-19 18:44:26 +00001470{
Paul Bakkerd98030e2009-05-02 15:13:40 +00001471 FILE *f;
Paul Bakker2b245eb2009-04-19 18:44:26 +00001472
Paul Bakkerd98030e2009-05-02 15:13:40 +00001473 if( ( f = fopen( path, "rb" ) ) == NULL )
1474 return( 1 );
Paul Bakker2b245eb2009-04-19 18:44:26 +00001475
Paul Bakkerd98030e2009-05-02 15:13:40 +00001476 fseek( f, 0, SEEK_END );
1477 *n = (size_t) ftell( f );
1478 fseek( f, 0, SEEK_SET );
Paul Bakker2b245eb2009-04-19 18:44:26 +00001479
Paul Bakkerd98030e2009-05-02 15:13:40 +00001480 if( ( *buf = (unsigned char *) malloc( *n + 1 ) ) == NULL )
1481 return( 1 );
Paul Bakker2b245eb2009-04-19 18:44:26 +00001482
Paul Bakkerd98030e2009-05-02 15:13:40 +00001483 if( fread( *buf, 1, *n, f ) != *n )
1484 {
1485 fclose( f );
1486 free( *buf );
1487 return( 1 );
1488 }
Paul Bakker2b245eb2009-04-19 18:44:26 +00001489
Paul Bakkerd98030e2009-05-02 15:13:40 +00001490 fclose( f );
Paul Bakker2b245eb2009-04-19 18:44:26 +00001491
Paul Bakkerd98030e2009-05-02 15:13:40 +00001492 (*buf)[*n] = '\0';
Paul Bakker2b245eb2009-04-19 18:44:26 +00001493
Paul Bakkerd98030e2009-05-02 15:13:40 +00001494 return( 0 );
Paul Bakker2b245eb2009-04-19 18:44:26 +00001495}
1496
1497/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001498 * Load one or more certificates and add them to the chained list
1499 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001500int x509parse_crtfile( x509_cert *chain, const char *path )
Paul Bakker5121ce52009-01-03 21:22:43 +00001501{
1502 int ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001503 size_t n;
1504 unsigned char *buf;
1505
Paul Bakker2b245eb2009-04-19 18:44:26 +00001506 if ( load_file( path, &buf, &n ) )
Paul Bakker5121ce52009-01-03 21:22:43 +00001507 return( 1 );
1508
Paul Bakker5121ce52009-01-03 21:22:43 +00001509 ret = x509parse_crt( chain, buf, (int) n );
1510
1511 memset( buf, 0, n + 1 );
1512 free( buf );
Paul Bakker5121ce52009-01-03 21:22:43 +00001513
1514 return( ret );
1515}
1516
Paul Bakkerd98030e2009-05-02 15:13:40 +00001517/*
1518 * Load one or more CRLs and add them to the chained list
1519 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001520int x509parse_crlfile( x509_crl *chain, const char *path )
Paul Bakkerd98030e2009-05-02 15:13:40 +00001521{
1522 int ret;
1523 size_t n;
1524 unsigned char *buf;
1525
1526 if ( load_file( path, &buf, &n ) )
1527 return( 1 );
1528
1529 ret = x509parse_crl( chain, buf, (int) n );
1530
1531 memset( buf, 0, n + 1 );
1532 free( buf );
1533
1534 return( ret );
1535}
1536
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00001537#if defined(POLARSSL_DES_C) && defined(POLARSSL_MD5_C)
Paul Bakker5121ce52009-01-03 21:22:43 +00001538/*
1539 * Read a 16-byte hex string and convert it to binary
1540 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001541static int x509_get_iv( const unsigned char *s, unsigned char iv[8] )
Paul Bakker5121ce52009-01-03 21:22:43 +00001542{
1543 int i, j, k;
1544
1545 memset( iv, 0, 8 );
1546
1547 for( i = 0; i < 16; i++, s++ )
1548 {
1549 if( *s >= '0' && *s <= '9' ) j = *s - '0'; else
1550 if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else
1551 if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else
Paul Bakker40e46942009-01-03 21:51:57 +00001552 return( POLARSSL_ERR_X509_KEY_INVALID_ENC_IV );
Paul Bakker5121ce52009-01-03 21:22:43 +00001553
1554 k = ( ( i & 1 ) != 0 ) ? j : j << 4;
1555
1556 iv[i >> 1] = (unsigned char)( iv[i >> 1] | k );
1557 }
1558
1559 return( 0 );
1560}
1561
1562/*
1563 * Decrypt with 3DES-CBC, using PBKDF1 for key derivation
1564 */
1565static void x509_des3_decrypt( unsigned char des3_iv[8],
1566 unsigned char *buf, int buflen,
Paul Bakkerff60ee62010-03-16 21:09:09 +00001567 const unsigned char *pwd, int pwdlen )
Paul Bakker5121ce52009-01-03 21:22:43 +00001568{
1569 md5_context md5_ctx;
1570 des3_context des3_ctx;
1571 unsigned char md5sum[16];
1572 unsigned char des3_key[24];
1573
1574 /*
1575 * 3DES key[ 0..15] = MD5(pwd || IV)
1576 * key[16..23] = MD5(pwd || IV || 3DES key[ 0..15])
1577 */
1578 md5_starts( &md5_ctx );
1579 md5_update( &md5_ctx, pwd, pwdlen );
1580 md5_update( &md5_ctx, des3_iv, 8 );
1581 md5_finish( &md5_ctx, md5sum );
1582 memcpy( des3_key, md5sum, 16 );
1583
1584 md5_starts( &md5_ctx );
1585 md5_update( &md5_ctx, md5sum, 16 );
1586 md5_update( &md5_ctx, pwd, pwdlen );
1587 md5_update( &md5_ctx, des3_iv, 8 );
1588 md5_finish( &md5_ctx, md5sum );
1589 memcpy( des3_key + 16, md5sum, 8 );
1590
1591 des3_set3key_dec( &des3_ctx, des3_key );
1592 des3_crypt_cbc( &des3_ctx, DES_DECRYPT, buflen,
1593 des3_iv, buf, buf );
1594
1595 memset( &md5_ctx, 0, sizeof( md5_ctx ) );
1596 memset( &des3_ctx, 0, sizeof( des3_ctx ) );
1597 memset( md5sum, 0, 16 );
1598 memset( des3_key, 0, 24 );
1599}
1600#endif
1601
1602/*
1603 * Parse a private RSA key
1604 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001605int x509parse_key( rsa_context *rsa, const unsigned char *key, int keylen,
1606 const unsigned char *pwd, int pwdlen )
Paul Bakker5121ce52009-01-03 21:22:43 +00001607{
1608 int ret, len, enc;
Paul Bakkerff60ee62010-03-16 21:09:09 +00001609 unsigned char *buf, *s1, *s2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001610 unsigned char *p, *end;
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00001611#if defined(POLARSSL_DES_C) && defined(POLARSSL_MD5_C)
Paul Bakker5121ce52009-01-03 21:22:43 +00001612 unsigned char des3_iv[8];
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00001613#else
1614 ((void) pwd);
1615 ((void) pwdlen);
1616#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00001617
Paul Bakkerff60ee62010-03-16 21:09:09 +00001618 s1 = (unsigned char *) strstr( (char *) key,
Paul Bakker5121ce52009-01-03 21:22:43 +00001619 "-----BEGIN RSA PRIVATE KEY-----" );
1620
1621 if( s1 != NULL )
1622 {
Paul Bakkerff60ee62010-03-16 21:09:09 +00001623 s2 = (unsigned char *) strstr( (char *) key,
Paul Bakker5121ce52009-01-03 21:22:43 +00001624 "-----END RSA PRIVATE KEY-----" );
1625
1626 if( s2 == NULL || s2 <= s1 )
Paul Bakker40e46942009-01-03 21:51:57 +00001627 return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001628
1629 s1 += 31;
1630 if( *s1 == '\r' ) s1++;
1631 if( *s1 == '\n' ) s1++;
Paul Bakker40e46942009-01-03 21:51:57 +00001632 else return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001633
1634 enc = 0;
1635
1636 if( memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 )
1637 {
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00001638#if defined(POLARSSL_DES_C) && defined(POLARSSL_MD5_C)
Paul Bakker5121ce52009-01-03 21:22:43 +00001639 enc++;
1640
1641 s1 += 22;
1642 if( *s1 == '\r' ) s1++;
1643 if( *s1 == '\n' ) s1++;
Paul Bakker40e46942009-01-03 21:51:57 +00001644 else return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001645
1646 if( memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001647 return( POLARSSL_ERR_X509_KEY_UNKNOWN_ENC_ALG );
Paul Bakker5121ce52009-01-03 21:22:43 +00001648
1649 s1 += 23;
1650 if( x509_get_iv( s1, des3_iv ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001651 return( POLARSSL_ERR_X509_KEY_INVALID_ENC_IV );
Paul Bakker5121ce52009-01-03 21:22:43 +00001652
1653 s1 += 16;
1654 if( *s1 == '\r' ) s1++;
1655 if( *s1 == '\n' ) s1++;
Paul Bakker40e46942009-01-03 21:51:57 +00001656 else return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001657#else
Paul Bakker40e46942009-01-03 21:51:57 +00001658 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001659#endif
1660 }
1661
1662 len = 0;
1663 ret = base64_decode( NULL, &len, s1, s2 - s1 );
1664
Paul Bakker40e46942009-01-03 21:51:57 +00001665 if( ret == POLARSSL_ERR_BASE64_INVALID_CHARACTER )
1666 return( ret | POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001667
1668 if( ( buf = (unsigned char *) malloc( len ) ) == NULL )
1669 return( 1 );
1670
1671 if( ( ret = base64_decode( buf, &len, s1, s2 - s1 ) ) != 0 )
1672 {
1673 free( buf );
Paul Bakker40e46942009-01-03 21:51:57 +00001674 return( ret | POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001675 }
1676
Paul Bakkerff60ee62010-03-16 21:09:09 +00001677 keylen = len;
Paul Bakker5121ce52009-01-03 21:22:43 +00001678
1679 if( enc != 0 )
1680 {
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00001681#if defined(POLARSSL_DES_C) && defined(POLARSSL_MD5_C)
Paul Bakker5121ce52009-01-03 21:22:43 +00001682 if( pwd == NULL )
1683 {
1684 free( buf );
Paul Bakker40e46942009-01-03 21:51:57 +00001685 return( POLARSSL_ERR_X509_KEY_PASSWORD_REQUIRED );
Paul Bakker5121ce52009-01-03 21:22:43 +00001686 }
1687
Paul Bakkerff60ee62010-03-16 21:09:09 +00001688 x509_des3_decrypt( des3_iv, buf, keylen, pwd, pwdlen );
Paul Bakker5121ce52009-01-03 21:22:43 +00001689
1690 if( buf[0] != 0x30 || buf[1] != 0x82 ||
1691 buf[4] != 0x02 || buf[5] != 0x01 )
1692 {
1693 free( buf );
Paul Bakker40e46942009-01-03 21:51:57 +00001694 return( POLARSSL_ERR_X509_KEY_PASSWORD_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001695 }
1696#else
Paul Bakker40e46942009-01-03 21:51:57 +00001697 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001698#endif
1699 }
1700 }
Paul Bakkerff60ee62010-03-16 21:09:09 +00001701 else
1702 {
1703 buf = NULL;
1704 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001705
1706 memset( rsa, 0, sizeof( rsa_context ) );
1707
Paul Bakkerff60ee62010-03-16 21:09:09 +00001708 p = ( s1 != NULL ) ? buf : (unsigned char *) key;
1709 end = p + keylen;
Paul Bakker5121ce52009-01-03 21:22:43 +00001710
1711 /*
1712 * RSAPrivateKey ::= SEQUENCE {
1713 * version Version,
1714 * modulus INTEGER, -- n
1715 * publicExponent INTEGER, -- e
1716 * privateExponent INTEGER, -- d
1717 * prime1 INTEGER, -- p
1718 * prime2 INTEGER, -- q
1719 * exponent1 INTEGER, -- d mod (p-1)
1720 * exponent2 INTEGER, -- d mod (q-1)
1721 * coefficient INTEGER, -- (inverse of q) mod p
1722 * otherPrimeInfos OtherPrimeInfos OPTIONAL
1723 * }
1724 */
1725 if( ( ret = asn1_get_tag( &p, end, &len,
1726 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1727 {
1728 if( s1 != NULL )
1729 free( buf );
1730
1731 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001732 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001733 }
1734
1735 end = p + len;
1736
1737 if( ( ret = asn1_get_int( &p, end, &rsa->ver ) ) != 0 )
1738 {
1739 if( s1 != NULL )
1740 free( buf );
1741
1742 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001743 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001744 }
1745
1746 if( rsa->ver != 0 )
1747 {
1748 if( s1 != NULL )
1749 free( buf );
1750
1751 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001752 return( ret | POLARSSL_ERR_X509_KEY_INVALID_VERSION );
Paul Bakker5121ce52009-01-03 21:22:43 +00001753 }
1754
1755 if( ( ret = asn1_get_mpi( &p, end, &rsa->N ) ) != 0 ||
1756 ( ret = asn1_get_mpi( &p, end, &rsa->E ) ) != 0 ||
1757 ( ret = asn1_get_mpi( &p, end, &rsa->D ) ) != 0 ||
1758 ( ret = asn1_get_mpi( &p, end, &rsa->P ) ) != 0 ||
1759 ( ret = asn1_get_mpi( &p, end, &rsa->Q ) ) != 0 ||
1760 ( ret = asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 ||
1761 ( ret = asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 ||
1762 ( ret = asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 )
1763 {
1764 if( s1 != NULL )
1765 free( buf );
1766
1767 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001768 return( ret | POLARSSL_ERR_X509_KEY_INVALID_FORMAT );
Paul Bakker5121ce52009-01-03 21:22:43 +00001769 }
1770
1771 rsa->len = mpi_size( &rsa->N );
1772
1773 if( p != end )
1774 {
1775 if( s1 != NULL )
1776 free( buf );
1777
1778 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001779 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT |
1780 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001781 }
1782
1783 if( ( ret = rsa_check_privkey( rsa ) ) != 0 )
1784 {
1785 if( s1 != NULL )
1786 free( buf );
1787
1788 rsa_free( rsa );
1789 return( ret );
1790 }
1791
1792 if( s1 != NULL )
1793 free( buf );
1794
1795 return( 0 );
1796}
1797
1798/*
1799 * Load and parse a private RSA key
1800 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001801int x509parse_keyfile( rsa_context *rsa, const char *path, const char *pwd )
Paul Bakker5121ce52009-01-03 21:22:43 +00001802{
1803 int ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001804 size_t n;
1805 unsigned char *buf;
1806
Paul Bakker2b245eb2009-04-19 18:44:26 +00001807 if ( load_file( path, &buf, &n ) )
Paul Bakker5121ce52009-01-03 21:22:43 +00001808 return( 1 );
1809
Paul Bakker5121ce52009-01-03 21:22:43 +00001810 if( pwd == NULL )
1811 ret = x509parse_key( rsa, buf, (int) n, NULL, 0 );
1812 else
1813 ret = x509parse_key( rsa, buf, (int) n,
1814 (unsigned char *) pwd, strlen( pwd ) );
1815
1816 memset( buf, 0, n + 1 );
1817 free( buf );
Paul Bakker5121ce52009-01-03 21:22:43 +00001818
1819 return( ret );
1820}
1821
1822#if defined _MSC_VER && !defined snprintf
Paul Bakkerd98030e2009-05-02 15:13:40 +00001823#include <stdarg.h>
1824
1825#if !defined vsnprintf
1826#define vsnprintf _vsnprintf
1827#endif // vsnprintf
1828
1829/*
1830 * Windows _snprintf and _vsnprintf are not compatible to linux versions.
1831 * Result value is not size of buffer needed, but -1 if no fit is possible.
1832 *
1833 * This fuction tries to 'fix' this by at least suggesting enlarging the
1834 * size by 20.
1835 */
1836int compat_snprintf(char *str, size_t size, const char *format, ...)
1837{
1838 va_list ap;
1839 int res = -1;
1840
1841 va_start( ap, format );
1842
1843 res = vsnprintf( str, size, format, ap );
1844
1845 va_end( ap );
1846
1847 // No quick fix possible
1848 if ( res < 0 )
1849 return( size + 20 );
1850
1851 return res;
1852}
1853
1854#define snprintf compat_snprintf
Paul Bakker5121ce52009-01-03 21:22:43 +00001855#endif
1856
Paul Bakkerd98030e2009-05-02 15:13:40 +00001857#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL -2
1858
1859#define SAFE_SNPRINTF() \
1860{ \
1861 if( ret == -1 ) \
1862 return( -1 ); \
1863 \
1864 if ( ret > n ) { \
1865 p[n - 1] = '\0'; \
1866 return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
1867 } \
1868 \
1869 n -= ret; \
1870 p += ret; \
1871}
1872
Paul Bakker5121ce52009-01-03 21:22:43 +00001873/*
1874 * Store the name in printable form into buf; no more
Paul Bakkerd98030e2009-05-02 15:13:40 +00001875 * than size characters will be written
Paul Bakker5121ce52009-01-03 21:22:43 +00001876 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001877int x509parse_dn_gets( char *buf, size_t size, const x509_name *dn )
Paul Bakker5121ce52009-01-03 21:22:43 +00001878{
Paul Bakkerd98030e2009-05-02 15:13:40 +00001879 int i, ret, n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001880 unsigned char c;
Paul Bakkerff60ee62010-03-16 21:09:09 +00001881 const x509_name *name;
Paul Bakker5121ce52009-01-03 21:22:43 +00001882 char s[128], *p;
1883
1884 memset( s, 0, sizeof( s ) );
1885
1886 name = dn;
1887 p = buf;
Paul Bakkerd98030e2009-05-02 15:13:40 +00001888 n = size;
Paul Bakker5121ce52009-01-03 21:22:43 +00001889
1890 while( name != NULL )
1891 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00001892 if( name != dn ) {
1893 ret = snprintf( p, n, ", " );
1894 SAFE_SNPRINTF();
1895 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001896
1897 if( memcmp( name->oid.p, OID_X520, 2 ) == 0 )
1898 {
1899 switch( name->oid.p[2] )
1900 {
1901 case X520_COMMON_NAME:
Paul Bakkerd98030e2009-05-02 15:13:40 +00001902 ret = snprintf( p, n, "CN=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00001903
1904 case X520_COUNTRY:
Paul Bakkerd98030e2009-05-02 15:13:40 +00001905 ret = snprintf( p, n, "C=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00001906
1907 case X520_LOCALITY:
Paul Bakkerd98030e2009-05-02 15:13:40 +00001908 ret = snprintf( p, n, "L=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00001909
1910 case X520_STATE:
Paul Bakkerd98030e2009-05-02 15:13:40 +00001911 ret = snprintf( p, n, "ST=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00001912
1913 case X520_ORGANIZATION:
Paul Bakkerd98030e2009-05-02 15:13:40 +00001914 ret = snprintf( p, n, "O=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00001915
1916 case X520_ORG_UNIT:
Paul Bakkerd98030e2009-05-02 15:13:40 +00001917 ret = snprintf( p, n, "OU=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00001918
1919 default:
Paul Bakkerd98030e2009-05-02 15:13:40 +00001920 ret = snprintf( p, n, "0x%02X=",
Paul Bakker5121ce52009-01-03 21:22:43 +00001921 name->oid.p[2] );
1922 break;
1923 }
Paul Bakkerd98030e2009-05-02 15:13:40 +00001924 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00001925 }
1926 else if( memcmp( name->oid.p, OID_PKCS9, 8 ) == 0 )
1927 {
1928 switch( name->oid.p[8] )
1929 {
1930 case PKCS9_EMAIL:
Paul Bakkerd98030e2009-05-02 15:13:40 +00001931 ret = snprintf( p, n, "emailAddress=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00001932
1933 default:
Paul Bakkerd98030e2009-05-02 15:13:40 +00001934 ret = snprintf( p, n, "0x%02X=",
Paul Bakker5121ce52009-01-03 21:22:43 +00001935 name->oid.p[8] );
1936 break;
1937 }
Paul Bakkerd98030e2009-05-02 15:13:40 +00001938 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00001939 }
1940 else
Paul Bakkerd98030e2009-05-02 15:13:40 +00001941 {
1942 ret = snprintf( p, n, "\?\?=" );
1943 SAFE_SNPRINTF();
1944 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001945
1946 for( i = 0; i < name->val.len; i++ )
1947 {
1948 if( i >= (int) sizeof( s ) - 1 )
1949 break;
1950
1951 c = name->val.p[i];
1952 if( c < 32 || c == 127 || ( c > 128 && c < 160 ) )
1953 s[i] = '?';
1954 else s[i] = c;
1955 }
1956 s[i] = '\0';
Paul Bakkerd98030e2009-05-02 15:13:40 +00001957 ret = snprintf( p, n, "%s", s );
1958 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00001959 name = name->next;
1960 }
1961
Paul Bakkerd98030e2009-05-02 15:13:40 +00001962 return( size - n );
Paul Bakker5121ce52009-01-03 21:22:43 +00001963}
1964
1965/*
Paul Bakkerd98030e2009-05-02 15:13:40 +00001966 * Return an informational string about the certificate.
Paul Bakker5121ce52009-01-03 21:22:43 +00001967 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001968int x509parse_cert_info( char *buf, size_t size, const char *prefix,
1969 const x509_cert *crt )
Paul Bakker5121ce52009-01-03 21:22:43 +00001970{
Paul Bakkerd98030e2009-05-02 15:13:40 +00001971 int i, n, nr, ret;
1972 char *p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001973
1974 p = buf;
Paul Bakkerd98030e2009-05-02 15:13:40 +00001975 n = size;
Paul Bakker5121ce52009-01-03 21:22:43 +00001976
Paul Bakkerd98030e2009-05-02 15:13:40 +00001977 ret = snprintf( p, n, "%scert. version : %d\n",
Paul Bakker5121ce52009-01-03 21:22:43 +00001978 prefix, crt->version );
Paul Bakkerd98030e2009-05-02 15:13:40 +00001979 SAFE_SNPRINTF();
1980 ret = snprintf( p, n, "%sserial number : ",
Paul Bakker5121ce52009-01-03 21:22:43 +00001981 prefix );
Paul Bakkerd98030e2009-05-02 15:13:40 +00001982 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00001983
Paul Bakkerd98030e2009-05-02 15:13:40 +00001984 nr = ( crt->serial.len <= 32 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001985 ? crt->serial.len : 32;
1986
Paul Bakkerd98030e2009-05-02 15:13:40 +00001987 for( i = 0; i < nr; i++ )
1988 {
1989 ret = snprintf( p, n, "%02X%s",
1990 crt->serial.p[i], ( i < nr - 1 ) ? ":" : "" );
1991 SAFE_SNPRINTF();
1992 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001993
Paul Bakkerd98030e2009-05-02 15:13:40 +00001994 ret = snprintf( p, n, "\n%sissuer name : ", prefix );
1995 SAFE_SNPRINTF();
1996 ret = x509parse_dn_gets( p, n, &crt->issuer );
1997 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00001998
Paul Bakkerd98030e2009-05-02 15:13:40 +00001999 ret = snprintf( p, n, "\n%ssubject name : ", prefix );
2000 SAFE_SNPRINTF();
2001 ret = x509parse_dn_gets( p, n, &crt->subject );
2002 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002003
Paul Bakkerd98030e2009-05-02 15:13:40 +00002004 ret = snprintf( p, n, "\n%sissued on : " \
Paul Bakker5121ce52009-01-03 21:22:43 +00002005 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
2006 crt->valid_from.year, crt->valid_from.mon,
2007 crt->valid_from.day, crt->valid_from.hour,
2008 crt->valid_from.min, crt->valid_from.sec );
Paul Bakkerd98030e2009-05-02 15:13:40 +00002009 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002010
Paul Bakkerd98030e2009-05-02 15:13:40 +00002011 ret = snprintf( p, n, "\n%sexpires on : " \
Paul Bakker5121ce52009-01-03 21:22:43 +00002012 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
2013 crt->valid_to.year, crt->valid_to.mon,
2014 crt->valid_to.day, crt->valid_to.hour,
2015 crt->valid_to.min, crt->valid_to.sec );
Paul Bakkerd98030e2009-05-02 15:13:40 +00002016 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002017
Paul Bakkerd98030e2009-05-02 15:13:40 +00002018 ret = snprintf( p, n, "\n%ssigned using : RSA+", prefix );
2019 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002020
Paul Bakker27d66162010-03-17 06:56:01 +00002021 switch( crt->sig_alg )
Paul Bakker5121ce52009-01-03 21:22:43 +00002022 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00002023 case SIG_RSA_MD2 : ret = snprintf( p, n, "MD2" ); break;
2024 case SIG_RSA_MD4 : ret = snprintf( p, n, "MD4" ); break;
2025 case SIG_RSA_MD5 : ret = snprintf( p, n, "MD5" ); break;
2026 case SIG_RSA_SHA1 : ret = snprintf( p, n, "SHA1" ); break;
2027 case SIG_RSA_SHA224 : ret = snprintf( p, n, "SHA224" ); break;
2028 case SIG_RSA_SHA256 : ret = snprintf( p, n, "SHA256" ); break;
2029 case SIG_RSA_SHA384 : ret = snprintf( p, n, "SHA384" ); break;
2030 case SIG_RSA_SHA512 : ret = snprintf( p, n, "SHA512" ); break;
2031 default: ret = snprintf( p, n, "???" ); break;
2032 }
2033 SAFE_SNPRINTF();
2034
2035 ret = snprintf( p, n, "\n%sRSA key size : %d bits\n", prefix,
2036 crt->rsa.N.n * (int) sizeof( unsigned long ) * 8 );
2037 SAFE_SNPRINTF();
2038
2039 return( size - n );
2040}
2041
2042/*
2043 * Return an informational string about the CRL.
2044 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00002045int x509parse_crl_info( char *buf, size_t size, const char *prefix,
2046 const x509_crl *crl )
Paul Bakkerd98030e2009-05-02 15:13:40 +00002047{
2048 int i, n, nr, ret;
2049 char *p;
Paul Bakkerff60ee62010-03-16 21:09:09 +00002050 const x509_crl_entry *entry;
Paul Bakkerd98030e2009-05-02 15:13:40 +00002051
2052 p = buf;
2053 n = size;
2054
2055 ret = snprintf( p, n, "%sCRL version : %d",
2056 prefix, crl->version );
2057 SAFE_SNPRINTF();
2058
2059 ret = snprintf( p, n, "\n%sissuer name : ", prefix );
2060 SAFE_SNPRINTF();
2061 ret = x509parse_dn_gets( p, n, &crl->issuer );
2062 SAFE_SNPRINTF();
2063
2064 ret = snprintf( p, n, "\n%sthis update : " \
2065 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
2066 crl->this_update.year, crl->this_update.mon,
2067 crl->this_update.day, crl->this_update.hour,
2068 crl->this_update.min, crl->this_update.sec );
2069 SAFE_SNPRINTF();
2070
2071 ret = snprintf( p, n, "\n%snext update : " \
2072 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
2073 crl->next_update.year, crl->next_update.mon,
2074 crl->next_update.day, crl->next_update.hour,
2075 crl->next_update.min, crl->next_update.sec );
2076 SAFE_SNPRINTF();
2077
2078 entry = &crl->entry;
2079
2080 ret = snprintf( p, n, "\n%sRevoked certificates:",
2081 prefix );
2082 SAFE_SNPRINTF();
2083
Paul Bakker9be19372009-07-27 20:21:53 +00002084 while( entry != NULL && entry->raw.len != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +00002085 {
2086 ret = snprintf( p, n, "\n%sserial number: ",
2087 prefix );
2088 SAFE_SNPRINTF();
2089
2090 nr = ( entry->serial.len <= 32 )
2091 ? entry->serial.len : 32;
2092
2093 for( i = 0; i < nr; i++ ) {
2094 ret = snprintf( p, n, "%02X%s",
2095 entry->serial.p[i], ( i < nr - 1 ) ? ":" : "" );
2096 SAFE_SNPRINTF();
2097 }
2098
2099 ret = snprintf( p, n, " revocation date: " \
2100 "%04d-%02d-%02d %02d:%02d:%02d",
2101 entry->revocation_date.year, entry->revocation_date.mon,
2102 entry->revocation_date.day, entry->revocation_date.hour,
2103 entry->revocation_date.min, entry->revocation_date.sec );
2104 SAFE_SNPRINTF();
2105
2106 entry = entry->next;
Paul Bakker5121ce52009-01-03 21:22:43 +00002107 }
2108
Paul Bakkerd98030e2009-05-02 15:13:40 +00002109 ret = snprintf( p, n, "\n%ssigned using : RSA+", prefix );
2110 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002111
Paul Bakker27d66162010-03-17 06:56:01 +00002112 switch( crl->sig_alg )
Paul Bakkerd98030e2009-05-02 15:13:40 +00002113 {
2114 case SIG_RSA_MD2 : ret = snprintf( p, n, "MD2" ); break;
2115 case SIG_RSA_MD4 : ret = snprintf( p, n, "MD4" ); break;
2116 case SIG_RSA_MD5 : ret = snprintf( p, n, "MD5" ); break;
2117 case SIG_RSA_SHA1 : ret = snprintf( p, n, "SHA1" ); break;
2118 case SIG_RSA_SHA224 : ret = snprintf( p, n, "SHA224" ); break;
2119 case SIG_RSA_SHA256 : ret = snprintf( p, n, "SHA256" ); break;
2120 case SIG_RSA_SHA384 : ret = snprintf( p, n, "SHA384" ); break;
2121 case SIG_RSA_SHA512 : ret = snprintf( p, n, "SHA512" ); break;
2122 default: ret = snprintf( p, n, "???" ); break;
2123 }
2124 SAFE_SNPRINTF();
2125
Paul Bakker1e27bb22009-07-19 20:25:25 +00002126 ret = snprintf( p, n, "\n" );
2127 SAFE_SNPRINTF();
2128
Paul Bakkerd98030e2009-05-02 15:13:40 +00002129 return( size - n );
Paul Bakker5121ce52009-01-03 21:22:43 +00002130}
2131
2132/*
Paul Bakker40ea7de2009-05-03 10:18:48 +00002133 * Return 0 if the x509_time is still valid, or 1 otherwise.
Paul Bakker5121ce52009-01-03 21:22:43 +00002134 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00002135int x509parse_time_expired( const x509_time *to )
Paul Bakker5121ce52009-01-03 21:22:43 +00002136{
2137 struct tm *lt;
2138 time_t tt;
2139
2140 tt = time( NULL );
2141 lt = localtime( &tt );
2142
Paul Bakker40ea7de2009-05-03 10:18:48 +00002143 if( lt->tm_year > to->year - 1900 )
2144 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002145
Paul Bakker40ea7de2009-05-03 10:18:48 +00002146 if( lt->tm_year == to->year - 1900 &&
2147 lt->tm_mon > to->mon - 1 )
2148 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002149
Paul Bakker40ea7de2009-05-03 10:18:48 +00002150 if( lt->tm_year == to->year - 1900 &&
2151 lt->tm_mon == to->mon - 1 &&
2152 lt->tm_mday > to->day )
2153 return( 1 );
2154
2155 return( 0 );
2156}
2157
2158/*
2159 * Return 1 if the certificate is revoked, or 0 otherwise.
2160 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00002161int x509parse_revoked( const x509_cert *crt, const x509_crl *crl )
Paul Bakker40ea7de2009-05-03 10:18:48 +00002162{
Paul Bakkerff60ee62010-03-16 21:09:09 +00002163 const x509_crl_entry *cur = &crl->entry;
Paul Bakker40ea7de2009-05-03 10:18:48 +00002164
2165 while( cur != NULL && cur->serial.len != 0 )
2166 {
2167 if( memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 )
2168 {
2169 if( x509parse_time_expired( &cur->revocation_date ) )
2170 return( 1 );
2171 }
2172
2173 cur = cur->next;
2174 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002175
2176 return( 0 );
2177}
2178
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002179/*
2180 * Wrapper for x509 hashes.
2181 *
2182 * @param out Buffer to receive the hash (Should be at least 64 bytes)
2183 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00002184static void x509_hash( const unsigned char *in, int len, int alg,
Paul Bakker5121ce52009-01-03 21:22:43 +00002185 unsigned char *out )
2186{
2187 switch( alg )
2188 {
Paul Bakker40e46942009-01-03 21:51:57 +00002189#if defined(POLARSSL_MD2_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00002190 case SIG_RSA_MD2 : md2( in, len, out ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002191#endif
Paul Bakker40e46942009-01-03 21:51:57 +00002192#if defined(POLARSSL_MD4_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00002193 case SIG_RSA_MD4 : md4( in, len, out ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002194#endif
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002195#if defined(POLARSSL_MD5_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00002196 case SIG_RSA_MD5 : md5( in, len, out ); break;
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002197#endif
2198#if defined(POLARSSL_SHA1_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00002199 case SIG_RSA_SHA1 : sha1( in, len, out ); break;
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002200#endif
Paul Bakker4593aea2009-02-09 22:32:35 +00002201#if defined(POLARSSL_SHA2_C)
2202 case SIG_RSA_SHA224 : sha2( in, len, out, 1 ); break;
2203 case SIG_RSA_SHA256 : sha2( in, len, out, 0 ); break;
2204#endif
Paul Bakkerfe1aea72009-10-03 20:09:14 +00002205#if defined(POLARSSL_SHA4_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00002206 case SIG_RSA_SHA384 : sha4( in, len, out, 1 ); break;
2207 case SIG_RSA_SHA512 : sha4( in, len, out, 0 ); break;
2208#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00002209 default:
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002210 memset( out, '\xFF', 64 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002211 break;
2212 }
2213}
2214
2215/*
2216 * Verify the certificate validity
2217 */
2218int x509parse_verify( x509_cert *crt,
2219 x509_cert *trust_ca,
Paul Bakker40ea7de2009-05-03 10:18:48 +00002220 x509_crl *ca_crl,
Paul Bakkerff60ee62010-03-16 21:09:09 +00002221 const char *cn, int *flags )
Paul Bakker5121ce52009-01-03 21:22:43 +00002222{
2223 int cn_len;
2224 int hash_id;
2225 int pathlen;
2226 x509_cert *cur;
2227 x509_name *name;
Paul Bakker4593aea2009-02-09 22:32:35 +00002228 unsigned char hash[64];
Paul Bakker5121ce52009-01-03 21:22:43 +00002229
Paul Bakker40ea7de2009-05-03 10:18:48 +00002230 *flags = 0;
2231
2232 if( x509parse_time_expired( &crt->valid_to ) )
2233 *flags = BADCERT_EXPIRED;
Paul Bakker5121ce52009-01-03 21:22:43 +00002234
2235 if( cn != NULL )
2236 {
2237 name = &crt->subject;
2238 cn_len = strlen( cn );
2239
2240 while( name != NULL )
2241 {
2242 if( memcmp( name->oid.p, OID_CN, 3 ) == 0 &&
2243 memcmp( name->val.p, cn, cn_len ) == 0 &&
2244 name->val.len == cn_len )
2245 break;
2246
2247 name = name->next;
2248 }
2249
2250 if( name == NULL )
2251 *flags |= BADCERT_CN_MISMATCH;
2252 }
2253
2254 *flags |= BADCERT_NOT_TRUSTED;
2255
2256 /*
2257 * Iterate upwards in the given cert chain,
2258 * ignoring any upper cert with CA != TRUE.
2259 */
2260 cur = crt->next;
2261
2262 pathlen = 1;
2263
Paul Bakker7c6d4a42009-03-28 20:35:47 +00002264 while( cur != NULL && cur->version != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002265 {
2266 if( cur->ca_istrue == 0 ||
2267 crt->issuer_raw.len != cur->subject_raw.len ||
2268 memcmp( crt->issuer_raw.p, cur->subject_raw.p,
2269 crt->issuer_raw.len ) != 0 )
2270 {
2271 cur = cur->next;
2272 continue;
2273 }
2274
Paul Bakker27d66162010-03-17 06:56:01 +00002275 hash_id = crt->sig_alg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002276
2277 x509_hash( crt->tbs.p, crt->tbs.len, hash_id, hash );
2278
2279 if( rsa_pkcs1_verify( &cur->rsa, RSA_PUBLIC, hash_id,
2280 0, hash, crt->sig.p ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00002281 return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +00002282
2283 pathlen++;
2284
2285 crt = cur;
2286 cur = crt->next;
2287 }
2288
2289 /*
2290 * Atempt to validate topmost cert with our CA chain.
2291 */
Paul Bakker7c6d4a42009-03-28 20:35:47 +00002292 while( trust_ca != NULL && trust_ca->version != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002293 {
2294 if( crt->issuer_raw.len != trust_ca->subject_raw.len ||
2295 memcmp( crt->issuer_raw.p, trust_ca->subject_raw.p,
2296 crt->issuer_raw.len ) != 0 )
2297 {
2298 trust_ca = trust_ca->next;
2299 continue;
2300 }
2301
2302 if( trust_ca->max_pathlen > 0 &&
2303 trust_ca->max_pathlen < pathlen )
2304 break;
2305
Paul Bakker27d66162010-03-17 06:56:01 +00002306 hash_id = crt->sig_alg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002307
2308 x509_hash( crt->tbs.p, crt->tbs.len, hash_id, hash );
2309
2310 if( rsa_pkcs1_verify( &trust_ca->rsa, RSA_PUBLIC, hash_id,
2311 0, hash, crt->sig.p ) == 0 )
2312 {
2313 /*
2314 * cert. is signed by a trusted CA
2315 */
2316 *flags &= ~BADCERT_NOT_TRUSTED;
2317 break;
2318 }
2319
2320 trust_ca = trust_ca->next;
2321 }
2322
Paul Bakker40ea7de2009-05-03 10:18:48 +00002323 /*
2324 * TODO: What happens if no CRL is present?
2325 * Suggestion: Revocation state should be unknown if no CRL is present.
2326 * For backwards compatibility this is not yet implemented.
2327 */
2328
2329 /*
2330 * Check if the topmost certificate is revoked if the trusted CA is
2331 * determined.
2332 */
2333 while( trust_ca != NULL && ca_crl != NULL && ca_crl->version != 0 )
2334 {
2335 if( ca_crl->issuer_raw.len != trust_ca->subject_raw.len ||
2336 memcmp( ca_crl->issuer_raw.p, trust_ca->subject_raw.p,
2337 ca_crl->issuer_raw.len ) != 0 )
2338 {
2339 ca_crl = ca_crl->next;
2340 continue;
2341 }
2342
2343 /*
2344 * Check if CRL is correctry signed by the trusted CA
2345 */
Paul Bakker27d66162010-03-17 06:56:01 +00002346 hash_id = ca_crl->sig_alg;
Paul Bakker40ea7de2009-05-03 10:18:48 +00002347
2348 x509_hash( ca_crl->tbs.p, ca_crl->tbs.len, hash_id, hash );
2349
2350 if( !rsa_pkcs1_verify( &trust_ca->rsa, RSA_PUBLIC, hash_id,
2351 0, hash, ca_crl->sig.p ) == 0 )
2352 {
2353 /*
2354 * CRL is not trusted
2355 */
2356 *flags |= BADCRL_NOT_TRUSTED;
2357 break;
2358 }
2359
2360 /*
2361 * Check for validity of CRL (Do not drop out)
2362 */
2363 if( x509parse_time_expired( &ca_crl->next_update ) )
2364 *flags |= BADCRL_EXPIRED;
2365
2366 /*
2367 * Check if certificate is revoked
2368 */
2369 if( x509parse_revoked(crt, ca_crl) )
2370 {
2371 *flags |= BADCERT_REVOKED;
2372 break;
2373 }
2374
2375 ca_crl = ca_crl->next;
2376 }
2377
Paul Bakker5121ce52009-01-03 21:22:43 +00002378 if( *flags != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00002379 return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +00002380
2381 return( 0 );
2382}
2383
2384/*
2385 * Unallocate all certificate data
2386 */
2387void x509_free( x509_cert *crt )
2388{
2389 x509_cert *cert_cur = crt;
2390 x509_cert *cert_prv;
2391 x509_name *name_cur;
2392 x509_name *name_prv;
2393
2394 if( crt == NULL )
2395 return;
2396
2397 do
2398 {
2399 rsa_free( &cert_cur->rsa );
2400
2401 name_cur = cert_cur->issuer.next;
2402 while( name_cur != NULL )
2403 {
2404 name_prv = name_cur;
2405 name_cur = name_cur->next;
2406 memset( name_prv, 0, sizeof( x509_name ) );
2407 free( name_prv );
2408 }
2409
2410 name_cur = cert_cur->subject.next;
2411 while( name_cur != NULL )
2412 {
2413 name_prv = name_cur;
2414 name_cur = name_cur->next;
2415 memset( name_prv, 0, sizeof( x509_name ) );
2416 free( name_prv );
2417 }
2418
2419 if( cert_cur->raw.p != NULL )
2420 {
2421 memset( cert_cur->raw.p, 0, cert_cur->raw.len );
2422 free( cert_cur->raw.p );
2423 }
2424
2425 cert_cur = cert_cur->next;
2426 }
2427 while( cert_cur != NULL );
2428
2429 cert_cur = crt;
2430 do
2431 {
2432 cert_prv = cert_cur;
2433 cert_cur = cert_cur->next;
2434
2435 memset( cert_prv, 0, sizeof( x509_cert ) );
2436 if( cert_prv != crt )
2437 free( cert_prv );
2438 }
2439 while( cert_cur != NULL );
2440}
2441
Paul Bakkerd98030e2009-05-02 15:13:40 +00002442/*
2443 * Unallocate all CRL data
2444 */
2445void x509_crl_free( x509_crl *crl )
2446{
2447 x509_crl *crl_cur = crl;
2448 x509_crl *crl_prv;
2449 x509_name *name_cur;
2450 x509_name *name_prv;
2451 x509_crl_entry *entry_cur;
2452 x509_crl_entry *entry_prv;
2453
2454 if( crl == NULL )
2455 return;
2456
2457 do
2458 {
2459 name_cur = crl_cur->issuer.next;
2460 while( name_cur != NULL )
2461 {
2462 name_prv = name_cur;
2463 name_cur = name_cur->next;
2464 memset( name_prv, 0, sizeof( x509_name ) );
2465 free( name_prv );
2466 }
2467
2468 entry_cur = crl_cur->entry.next;
2469 while( entry_cur != NULL )
2470 {
2471 entry_prv = entry_cur;
2472 entry_cur = entry_cur->next;
2473 memset( entry_prv, 0, sizeof( x509_crl_entry ) );
2474 free( entry_prv );
2475 }
2476
2477 if( crl_cur->raw.p != NULL )
2478 {
2479 memset( crl_cur->raw.p, 0, crl_cur->raw.len );
2480 free( crl_cur->raw.p );
2481 }
2482
2483 crl_cur = crl_cur->next;
2484 }
2485 while( crl_cur != NULL );
2486
2487 crl_cur = crl;
2488 do
2489 {
2490 crl_prv = crl_cur;
2491 crl_cur = crl_cur->next;
2492
2493 memset( crl_prv, 0, sizeof( x509_crl ) );
2494 if( crl_prv != crl )
2495 free( crl_prv );
2496 }
2497 while( crl_cur != NULL );
2498}
2499
Paul Bakker40e46942009-01-03 21:51:57 +00002500#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002501
Paul Bakker40e46942009-01-03 21:51:57 +00002502#include "polarssl/certs.h"
Paul Bakker5121ce52009-01-03 21:22:43 +00002503
2504/*
2505 * Checkup routine
2506 */
2507int x509_self_test( int verbose )
2508{
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002509#if defined(POLARSSL_MD5_C)
Paul Bakker5121ce52009-01-03 21:22:43 +00002510 int ret, i, j;
2511 x509_cert cacert;
2512 x509_cert clicert;
2513 rsa_context rsa;
2514
2515 if( verbose != 0 )
2516 printf( " X.509 certificate load: " );
2517
2518 memset( &clicert, 0, sizeof( x509_cert ) );
2519
2520 ret = x509parse_crt( &clicert, (unsigned char *) test_cli_crt,
2521 strlen( test_cli_crt ) );
2522 if( ret != 0 )
2523 {
2524 if( verbose != 0 )
2525 printf( "failed\n" );
2526
2527 return( ret );
2528 }
2529
2530 memset( &cacert, 0, sizeof( x509_cert ) );
2531
2532 ret = x509parse_crt( &cacert, (unsigned char *) test_ca_crt,
2533 strlen( test_ca_crt ) );
2534 if( ret != 0 )
2535 {
2536 if( verbose != 0 )
2537 printf( "failed\n" );
2538
2539 return( ret );
2540 }
2541
2542 if( verbose != 0 )
2543 printf( "passed\n X.509 private key load: " );
2544
2545 i = strlen( test_ca_key );
2546 j = strlen( test_ca_pwd );
2547
2548 if( ( ret = x509parse_key( &rsa,
2549 (unsigned char *) test_ca_key, i,
2550 (unsigned char *) test_ca_pwd, j ) ) != 0 )
2551 {
2552 if( verbose != 0 )
2553 printf( "failed\n" );
2554
2555 return( ret );
2556 }
2557
2558 if( verbose != 0 )
2559 printf( "passed\n X.509 signature verify: ");
2560
Paul Bakker1973e4c2009-07-10 22:32:40 +00002561 ret = x509parse_verify( &clicert, &cacert, NULL, "PolarSSL Client 2", &i );
Paul Bakker5121ce52009-01-03 21:22:43 +00002562 if( ret != 0 )
2563 {
2564 if( verbose != 0 )
2565 printf( "failed\n" );
2566
2567 return( ret );
2568 }
2569
2570 if( verbose != 0 )
2571 printf( "passed\n\n" );
2572
2573 x509_free( &cacert );
2574 x509_free( &clicert );
2575 rsa_free( &rsa );
2576
2577 return( 0 );
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002578#else
2579 ((void) verbose);
2580 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
2581#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00002582}
2583
2584#endif
2585
2586#endif