blob: c316c034b015bd972055ef859596e8768cb2440a [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * X.509 certificate and private key decoding
3 *
Paul Bakkerfc8c4362010-03-21 17:37:16 +00004 * Copyright (C) 2006-2010, Paul Bakker <polarssl_maintainer at polarssl.org>
Paul Bakker77b385e2009-07-28 17:23:11 +00005 * All rights reserved.
Paul Bakkere0ccd0a2009-01-04 16:27:10 +00006 *
Paul Bakker5121ce52009-01-03 21:22:43 +00007 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21/*
22 * The ITU-T X.509 standard defines a certificat format for PKI.
23 *
24 * http://www.ietf.org/rfc/rfc2459.txt
25 * http://www.ietf.org/rfc/rfc3279.txt
26 *
27 * ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
28 *
29 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
30 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
31 */
32
Paul Bakker40e46942009-01-03 21:51:57 +000033#include "polarssl/config.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000034
Paul Bakker40e46942009-01-03 21:51:57 +000035#if defined(POLARSSL_X509_PARSE_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000036
Paul Bakker40e46942009-01-03 21:51:57 +000037#include "polarssl/x509.h"
38#include "polarssl/base64.h"
39#include "polarssl/des.h"
40#include "polarssl/md2.h"
41#include "polarssl/md4.h"
42#include "polarssl/md5.h"
43#include "polarssl/sha1.h"
Paul Bakker026c03b2009-03-28 17:53:03 +000044#include "polarssl/sha2.h"
45#include "polarssl/sha4.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000046
47#include <string.h>
48#include <stdlib.h>
49#include <stdio.h>
50#include <time.h>
51
52/*
53 * ASN.1 DER decoding routines
54 */
55static int asn1_get_len( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +000056 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +000057 int *len )
58{
59 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +000060 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000061
62 if( ( **p & 0x80 ) == 0 )
63 *len = *(*p)++;
64 else
65 {
66 switch( **p & 0x7F )
67 {
68 case 1:
69 if( ( end - *p ) < 2 )
Paul Bakker40e46942009-01-03 21:51:57 +000070 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000071
72 *len = (*p)[1];
73 (*p) += 2;
74 break;
75
76 case 2:
77 if( ( end - *p ) < 3 )
Paul Bakker40e46942009-01-03 21:51:57 +000078 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000079
80 *len = ( (*p)[1] << 8 ) | (*p)[2];
81 (*p) += 3;
82 break;
83
84 default:
Paul Bakker40e46942009-01-03 21:51:57 +000085 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
Paul Bakker5121ce52009-01-03 21:22:43 +000086 break;
87 }
88 }
89
90 if( *len > (int) ( end - *p ) )
Paul Bakker40e46942009-01-03 21:51:57 +000091 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000092
93 return( 0 );
94}
95
96static int asn1_get_tag( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +000097 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +000098 int *len, int tag )
99{
100 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000101 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000102
103 if( **p != tag )
Paul Bakker40e46942009-01-03 21:51:57 +0000104 return( POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000105
106 (*p)++;
107
108 return( asn1_get_len( p, end, len ) );
109}
110
111static int asn1_get_bool( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000112 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000113 int *val )
114{
115 int ret, len;
116
117 if( ( ret = asn1_get_tag( p, end, &len, ASN1_BOOLEAN ) ) != 0 )
118 return( ret );
119
120 if( len != 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000121 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000122
123 *val = ( **p != 0 ) ? 1 : 0;
124 (*p)++;
125
126 return( 0 );
127}
128
129static int asn1_get_int( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000130 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000131 int *val )
132{
133 int ret, len;
134
135 if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
136 return( ret );
137
138 if( len > (int) sizeof( int ) || ( **p & 0x80 ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000139 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000140
141 *val = 0;
142
143 while( len-- > 0 )
144 {
145 *val = ( *val << 8 ) | **p;
146 (*p)++;
147 }
148
149 return( 0 );
150}
151
152static int asn1_get_mpi( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000153 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000154 mpi *X )
155{
156 int ret, len;
157
158 if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
159 return( ret );
160
161 ret = mpi_read_binary( X, *p, len );
162
163 *p += len;
164
165 return( ret );
166}
167
168/*
169 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
170 */
171static int x509_get_version( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000172 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000173 int *ver )
174{
175 int ret, len;
176
177 if( ( ret = asn1_get_tag( p, end, &len,
178 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) != 0 )
179 {
Paul Bakker40e46942009-01-03 21:51:57 +0000180 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker5121ce52009-01-03 21:22:43 +0000181 return( *ver = 0 );
182
183 return( ret );
184 }
185
186 end = *p + len;
187
188 if( ( ret = asn1_get_int( p, end, ver ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000189 return( POLARSSL_ERR_X509_CERT_INVALID_VERSION | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000190
191 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000192 return( POLARSSL_ERR_X509_CERT_INVALID_VERSION |
193 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000194
195 return( 0 );
196}
197
198/*
199 * CertificateSerialNumber ::= INTEGER
200 */
201static int x509_get_serial( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000202 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000203 x509_buf *serial )
204{
205 int ret;
206
207 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000208 return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL |
209 POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000210
211 if( **p != ( ASN1_CONTEXT_SPECIFIC | ASN1_PRIMITIVE | 2 ) &&
212 **p != ASN1_INTEGER )
Paul Bakker40e46942009-01-03 21:51:57 +0000213 return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL |
214 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000215
216 serial->tag = *(*p)++;
217
218 if( ( ret = asn1_get_len( p, end, &serial->len ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000219 return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000220
221 serial->p = *p;
222 *p += serial->len;
223
224 return( 0 );
225}
226
227/*
228 * AlgorithmIdentifier ::= SEQUENCE {
229 * algorithm OBJECT IDENTIFIER,
230 * parameters ANY DEFINED BY algorithm OPTIONAL }
231 */
232static int x509_get_alg( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000233 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000234 x509_buf *alg )
235{
236 int ret, len;
237
238 if( ( ret = asn1_get_tag( p, end, &len,
239 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000240 return( POLARSSL_ERR_X509_CERT_INVALID_ALG | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000241
242 end = *p + len;
243 alg->tag = **p;
244
245 if( ( ret = asn1_get_tag( p, end, &alg->len, ASN1_OID ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000246 return( POLARSSL_ERR_X509_CERT_INVALID_ALG | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000247
248 alg->p = *p;
249 *p += alg->len;
250
251 if( *p == end )
252 return( 0 );
253
254 /*
255 * assume the algorithm parameters must be NULL
256 */
257 if( ( ret = asn1_get_tag( p, end, &len, ASN1_NULL ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000258 return( POLARSSL_ERR_X509_CERT_INVALID_ALG | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000259
260 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000261 return( POLARSSL_ERR_X509_CERT_INVALID_ALG |
262 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000263
264 return( 0 );
265}
266
267/*
268 * RelativeDistinguishedName ::=
269 * SET OF AttributeTypeAndValue
270 *
271 * AttributeTypeAndValue ::= SEQUENCE {
272 * type AttributeType,
273 * value AttributeValue }
274 *
275 * AttributeType ::= OBJECT IDENTIFIER
276 *
277 * AttributeValue ::= ANY DEFINED BY AttributeType
278 */
279static int x509_get_name( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000280 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000281 x509_name *cur )
282{
283 int ret, len;
Paul Bakkerff60ee62010-03-16 21:09:09 +0000284 const unsigned char *end2;
Paul Bakker5121ce52009-01-03 21:22:43 +0000285 x509_buf *oid;
286 x509_buf *val;
287
288 if( ( ret = asn1_get_tag( p, end, &len,
289 ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000290 return( POLARSSL_ERR_X509_CERT_INVALID_NAME | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000291
292 end2 = end;
293 end = *p + len;
294
295 if( ( ret = asn1_get_tag( p, end, &len,
296 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000297 return( POLARSSL_ERR_X509_CERT_INVALID_NAME | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000298
299 if( *p + len != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000300 return( POLARSSL_ERR_X509_CERT_INVALID_NAME |
301 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000302
303 oid = &cur->oid;
304 oid->tag = **p;
305
306 if( ( ret = asn1_get_tag( p, end, &oid->len, ASN1_OID ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000307 return( POLARSSL_ERR_X509_CERT_INVALID_NAME | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000308
309 oid->p = *p;
310 *p += oid->len;
311
312 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000313 return( POLARSSL_ERR_X509_CERT_INVALID_NAME |
314 POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000315
316 if( **p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING &&
317 **p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING &&
318 **p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING )
Paul Bakker40e46942009-01-03 21:51:57 +0000319 return( POLARSSL_ERR_X509_CERT_INVALID_NAME |
320 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000321
322 val = &cur->val;
323 val->tag = *(*p)++;
324
325 if( ( ret = asn1_get_len( p, end, &val->len ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000326 return( POLARSSL_ERR_X509_CERT_INVALID_NAME | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000327
328 val->p = *p;
329 *p += val->len;
330
331 cur->next = NULL;
332
333 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000334 return( POLARSSL_ERR_X509_CERT_INVALID_NAME |
335 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000336
337 /*
338 * recurse until end of SEQUENCE is reached
339 */
340 if( *p == end2 )
341 return( 0 );
342
343 cur->next = (x509_name *) malloc(
344 sizeof( x509_name ) );
345
346 if( cur->next == NULL )
347 return( 1 );
348
349 return( x509_get_name( p, end2, cur->next ) );
350}
351
352/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000353 * Time ::= CHOICE {
354 * utcTime UTCTime,
355 * generalTime GeneralizedTime }
356 */
Paul Bakker91200182010-02-18 21:26:15 +0000357static int x509_get_time( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000358 const unsigned char *end,
Paul Bakkerd98030e2009-05-02 15:13:40 +0000359 x509_time *time )
360{
361 int ret, len;
362 char date[64];
Paul Bakker91200182010-02-18 21:26:15 +0000363 unsigned char tag;
Paul Bakkerd98030e2009-05-02 15:13:40 +0000364
Paul Bakker91200182010-02-18 21:26:15 +0000365 if( ( end - *p ) < 1 )
366 return( POLARSSL_ERR_X509_CERT_INVALID_DATE | POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakkerd98030e2009-05-02 15:13:40 +0000367
Paul Bakker91200182010-02-18 21:26:15 +0000368 tag = **p;
Paul Bakkerd98030e2009-05-02 15:13:40 +0000369
Paul Bakker91200182010-02-18 21:26:15 +0000370 if ( tag == ASN1_UTC_TIME )
371 {
372 (*p)++;
373 ret = asn1_get_len( p, end, &len );
374
375 if( ret != 0 )
376 return( POLARSSL_ERR_X509_CERT_INVALID_DATE | ret );
Paul Bakkerd98030e2009-05-02 15:13:40 +0000377
Paul Bakker91200182010-02-18 21:26:15 +0000378 memset( date, 0, sizeof( date ) );
379 memcpy( date, *p, ( len < (int) sizeof( date ) - 1 ) ?
380 len : (int) sizeof( date ) - 1 );
Paul Bakkerd98030e2009-05-02 15:13:40 +0000381
Paul Bakker91200182010-02-18 21:26:15 +0000382 if( sscanf( date, "%2d%2d%2d%2d%2d%2d",
383 &time->year, &time->mon, &time->day,
384 &time->hour, &time->min, &time->sec ) < 5 )
385 return( POLARSSL_ERR_X509_CERT_INVALID_DATE );
Paul Bakkerd98030e2009-05-02 15:13:40 +0000386
Paul Bakker91200182010-02-18 21:26:15 +0000387 time->year += 100 * ( time->year < 90 );
388 time->year += 1900;
389
390 *p += len;
391
392 return( 0 );
393 }
394 else if ( tag == ASN1_GENERALIZED_TIME )
395 {
396 (*p)++;
397 ret = asn1_get_len( p, end, &len );
398
399 if( ret != 0 )
400 return( POLARSSL_ERR_X509_CERT_INVALID_DATE | ret );
401
402 memset( date, 0, sizeof( date ) );
403 memcpy( date, *p, ( len < (int) sizeof( date ) - 1 ) ?
404 len : (int) sizeof( date ) - 1 );
405
406 if( sscanf( date, "%4d%2d%2d%2d%2d%2d",
407 &time->year, &time->mon, &time->day,
408 &time->hour, &time->min, &time->sec ) < 5 )
409 return( POLARSSL_ERR_X509_CERT_INVALID_DATE );
410
411 *p += len;
412
413 return( 0 );
414 }
415 else
416 return( POLARSSL_ERR_X509_CERT_INVALID_DATE | POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakkerd98030e2009-05-02 15:13:40 +0000417}
418
419
420/*
421 * Validity ::= SEQUENCE {
422 * notBefore Time,
423 * notAfter Time }
424 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000425static int x509_get_dates( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000426 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000427 x509_time *from,
428 x509_time *to )
429{
430 int ret, len;
Paul Bakker5121ce52009-01-03 21:22:43 +0000431
432 if( ( ret = asn1_get_tag( p, end, &len,
433 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000434 return( POLARSSL_ERR_X509_CERT_INVALID_DATE | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000435
436 end = *p + len;
437
Paul Bakker91200182010-02-18 21:26:15 +0000438 if( ( ret = x509_get_time( p, end, from ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +0000439 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000440
Paul Bakker91200182010-02-18 21:26:15 +0000441 if( ( ret = x509_get_time( p, end, to ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +0000442 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000443
444 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000445 return( POLARSSL_ERR_X509_CERT_INVALID_DATE |
446 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000447
448 return( 0 );
449}
450
451/*
452 * SubjectPublicKeyInfo ::= SEQUENCE {
453 * algorithm AlgorithmIdentifier,
454 * subjectPublicKey BIT STRING }
455 */
456static int x509_get_pubkey( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000457 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000458 x509_buf *pk_alg_oid,
459 mpi *N, mpi *E )
460{
461 int ret, len;
462 unsigned char *end2;
463
464 if( ( ret = x509_get_alg( p, end, pk_alg_oid ) ) != 0 )
465 return( ret );
466
467 /*
468 * only RSA public keys handled at this time
469 */
470 if( pk_alg_oid->len != 9 ||
471 memcmp( pk_alg_oid->p, OID_PKCS1_RSA, 9 ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000472 return( POLARSSL_ERR_X509_CERT_UNKNOWN_PK_ALG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000473
474 if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000475 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000476
477 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000478 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY |
479 POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000480
481 end2 = *p + len;
482
483 if( *(*p)++ != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000484 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY );
Paul Bakker5121ce52009-01-03 21:22:43 +0000485
486 /*
487 * RSAPublicKey ::= SEQUENCE {
488 * modulus INTEGER, -- n
489 * publicExponent INTEGER -- e
490 * }
491 */
492 if( ( ret = asn1_get_tag( p, end2, &len,
493 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000494 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000495
496 if( *p + len != end2 )
Paul Bakker40e46942009-01-03 21:51:57 +0000497 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY |
498 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000499
500 if( ( ret = asn1_get_mpi( p, end2, N ) ) != 0 ||
501 ( ret = asn1_get_mpi( p, end2, E ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000502 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000503
504 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000505 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY |
506 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000507
508 return( 0 );
509}
510
511static int x509_get_sig( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000512 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000513 x509_buf *sig )
514{
515 int ret, len;
516
517 sig->tag = **p;
518
519 if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000520 return( POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000521
522 if( --len < 1 || *(*p)++ != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000523 return( POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000524
525 sig->len = len;
526 sig->p = *p;
527
528 *p += len;
529
530 return( 0 );
531}
532
533/*
534 * X.509 v2/v3 unique identifier (not parsed)
535 */
536static int x509_get_uid( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000537 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000538 x509_buf *uid, int n )
539{
540 int ret;
541
542 if( *p == end )
543 return( 0 );
544
545 uid->tag = **p;
546
547 if( ( ret = asn1_get_tag( p, end, &uid->len,
548 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | n ) ) != 0 )
549 {
Paul Bakker40e46942009-01-03 21:51:57 +0000550 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker5121ce52009-01-03 21:22:43 +0000551 return( 0 );
552
553 return( ret );
554 }
555
556 uid->p = *p;
557 *p += uid->len;
558
559 return( 0 );
560}
561
562/*
Paul Bakkerd98030e2009-05-02 15:13:40 +0000563 * X.509 Extensions (No parsing of extensions, pointer should
564 * be either manually updated or extensions should be parsed!
Paul Bakker5121ce52009-01-03 21:22:43 +0000565 */
566static int x509_get_ext( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000567 const unsigned char *end,
Paul Bakkerd98030e2009-05-02 15:13:40 +0000568 x509_buf *ext )
Paul Bakker5121ce52009-01-03 21:22:43 +0000569{
570 int ret, len;
Paul Bakker5121ce52009-01-03 21:22:43 +0000571
572 if( *p == end )
573 return( 0 );
574
575 ext->tag = **p;
Paul Bakkerff60ee62010-03-16 21:09:09 +0000576
Paul Bakker5121ce52009-01-03 21:22:43 +0000577 if( ( ret = asn1_get_tag( p, end, &ext->len,
578 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000579 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000580
581 ext->p = *p;
582 end = *p + ext->len;
583
584 /*
585 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
586 *
587 * Extension ::= SEQUENCE {
588 * extnID OBJECT IDENTIFIER,
589 * critical BOOLEAN DEFAULT FALSE,
590 * extnValue OCTET STRING }
591 */
592 if( ( ret = asn1_get_tag( p, end, &len,
593 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000594 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000595
596 if( end != *p + len )
Paul Bakker40e46942009-01-03 21:51:57 +0000597 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
598 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000599
Paul Bakkerd98030e2009-05-02 15:13:40 +0000600 return( 0 );
601}
602
603/*
604 * X.509 CRL v2 extensions (no extensions parsed yet.)
605 */
606static int x509_get_crl_ext( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000607 const unsigned char *end,
608 x509_buf *ext )
Paul Bakkerd98030e2009-05-02 15:13:40 +0000609{
610 int ret, len;
611
612 if( ( ret = x509_get_ext( p, end, ext ) ) != 0 )
613 {
614 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
615 return( 0 );
616
617 return( ret );
618 }
619
620 while( *p < end )
621 {
622 if( ( ret = asn1_get_tag( p, end, &len,
623 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
624 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
625
626 *p += len;
627 }
628
629 if( *p != end )
630 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
631 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
632
633 return( 0 );
634}
635
636/*
637 * X.509 v3 extensions (only BasicConstraints are parsed)
638 */
639static int x509_get_crt_ext( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000640 const unsigned char *end,
641 x509_buf *ext,
642 int *ca_istrue,
643 int *max_pathlen )
Paul Bakkerd98030e2009-05-02 15:13:40 +0000644{
645 int ret, len;
646 int is_critical = 1;
647 int is_cacert = 0;
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000648 unsigned char *end_ext_data, *end_ext_octet;
Paul Bakkerd98030e2009-05-02 15:13:40 +0000649
650 if( ( ret = x509_get_ext( p, end, ext ) ) != 0 )
651 {
652 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
653 return( 0 );
654
655 return( ret );
656 }
657
Paul Bakker5121ce52009-01-03 21:22:43 +0000658 while( *p < end )
659 {
660 if( ( ret = asn1_get_tag( p, end, &len,
661 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000662 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000663
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000664 end_ext_data = *p + len;
665
Paul Bakker5121ce52009-01-03 21:22:43 +0000666 if( memcmp( *p, "\x06\x03\x55\x1D\x13", 5 ) != 0 )
667 {
668 *p += len;
669 continue;
670 }
671
672 *p += 5;
673
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000674 if( ( ret = asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 &&
Paul Bakker40e46942009-01-03 21:51:57 +0000675 ( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) )
676 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000677
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000678 if( ( ret = asn1_get_tag( p, end_ext_data, &len,
Paul Bakker5121ce52009-01-03 21:22:43 +0000679 ASN1_OCTET_STRING ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000680 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000681
682 /*
683 * BasicConstraints ::= SEQUENCE {
684 * cA BOOLEAN DEFAULT FALSE,
685 * pathLenConstraint INTEGER (0..MAX) OPTIONAL }
686 */
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000687 end_ext_octet = *p + len;
Paul Bakkerff60ee62010-03-16 21:09:09 +0000688
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000689 if( end_ext_octet != end_ext_data )
690 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
691 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000692
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000693 if( ( ret = asn1_get_tag( p, end_ext_octet, &len,
Paul Bakker5121ce52009-01-03 21:22:43 +0000694 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000695 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000696
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000697 if( *p == end_ext_octet )
Paul Bakker5121ce52009-01-03 21:22:43 +0000698 continue;
699
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000700 if( ( ret = asn1_get_bool( p, end_ext_octet, &is_cacert ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000701 {
Paul Bakker40e46942009-01-03 21:51:57 +0000702 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000703 ret = asn1_get_int( p, end_ext_octet, &is_cacert );
Paul Bakker5121ce52009-01-03 21:22:43 +0000704
705 if( ret != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000706 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000707
708 if( is_cacert != 0 )
709 is_cacert = 1;
710 }
711
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000712 if( *p == end_ext_octet )
Paul Bakker5121ce52009-01-03 21:22:43 +0000713 continue;
714
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000715 if( ( ret = asn1_get_int( p, end_ext_octet, max_pathlen ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000716 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000717
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000718 if( *p != end_ext_octet )
Paul Bakker40e46942009-01-03 21:51:57 +0000719 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
720 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000721
722 max_pathlen++;
723 }
724
725 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000726 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
727 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000728
729 *ca_istrue = is_critical & is_cacert;
730
731 return( 0 );
732}
733
734/*
Paul Bakkerd98030e2009-05-02 15:13:40 +0000735 * X.509 CRL Entries
736 */
737static int x509_get_entries( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000738 const unsigned char *end,
Paul Bakkerd98030e2009-05-02 15:13:40 +0000739 x509_crl_entry *entry )
740{
Paul Bakker9be19372009-07-27 20:21:53 +0000741 int ret, entry_len;
Paul Bakkerd98030e2009-05-02 15:13:40 +0000742 x509_crl_entry *cur_entry = entry;
743
744 if( *p == end )
745 return( 0 );
746
Paul Bakker9be19372009-07-27 20:21:53 +0000747 if( ( ret = asn1_get_tag( p, end, &entry_len,
Paul Bakkerd98030e2009-05-02 15:13:40 +0000748 ASN1_SEQUENCE | ASN1_CONSTRUCTED ) ) != 0 )
749 {
750 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
751 return( 0 );
752
753 return( ret );
754 }
755
Paul Bakker9be19372009-07-27 20:21:53 +0000756 end = *p + entry_len;
Paul Bakkerd98030e2009-05-02 15:13:40 +0000757
758 while( *p < end )
759 {
760 int len2;
761
762 if( ( ret = asn1_get_tag( p, end, &len2,
763 ASN1_SEQUENCE | ASN1_CONSTRUCTED ) ) != 0 )
764 {
Paul Bakkerd98030e2009-05-02 15:13:40 +0000765 return( ret );
766 }
767
Paul Bakker9be19372009-07-27 20:21:53 +0000768 cur_entry->raw.tag = **p;
769 cur_entry->raw.p = *p;
770 cur_entry->raw.len = len2;
771
Paul Bakkerd98030e2009-05-02 15:13:40 +0000772 if( ( ret = x509_get_serial( p, end, &cur_entry->serial ) ) != 0 )
773 return( ret );
774
Paul Bakker91200182010-02-18 21:26:15 +0000775 if( ( ret = x509_get_time( p, end, &cur_entry->revocation_date ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +0000776 return( ret );
777
778 if( ( ret = x509_get_crl_ext( p, end, &cur_entry->entry_ext ) ) != 0 )
779 return( ret );
780
781 if ( *p < end ) {
782 cur_entry->next = malloc( sizeof( x509_crl_entry ) );
783 cur_entry = cur_entry->next;
784 memset( cur_entry, 0, sizeof( x509_crl_entry ) );
785 }
786 }
787
788 return( 0 );
789}
790
Paul Bakker27d66162010-03-17 06:56:01 +0000791static int x509_get_sig_alg( const x509_buf *sig_oid, int *sig_alg )
792{
793 if( sig_oid->len == 9 &&
794 memcmp( sig_oid->p, OID_PKCS1, 8 ) == 0 )
795 {
796 if( sig_oid->p[8] >= 2 && sig_oid->p[8] <= 5 )
797 {
798 *sig_alg = sig_oid->p[8];
799 return( 0 );
800 }
801
802 if ( sig_oid->p[8] >= 11 && sig_oid->p[8] <= 14 )
803 {
804 *sig_alg = sig_oid->p[8];
805 return( 0 );
806 }
807
808 return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
809 }
810
811 return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
812}
813
Paul Bakkerd98030e2009-05-02 15:13:40 +0000814/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000815 * Parse one or more certificates and add them to the chained list
816 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000817int x509parse_crt( x509_cert *chain, const unsigned char *buf, int buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000818{
819 int ret, len;
Paul Bakkerff60ee62010-03-16 21:09:09 +0000820 const unsigned char *s1, *s2;
Paul Bakker5121ce52009-01-03 21:22:43 +0000821 unsigned char *p, *end;
822 x509_cert *crt;
823
824 crt = chain;
825
Paul Bakker320a4b52009-03-28 18:52:39 +0000826 /*
827 * Check for valid input
828 */
829 if( crt == NULL || buf == NULL )
830 return( 1 );
831
Paul Bakkere9581d62009-03-28 20:29:25 +0000832 while( crt->version != 0 && crt->next != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000833 crt = crt->next;
834
835 /*
Paul Bakker320a4b52009-03-28 18:52:39 +0000836 * Add new certificate on the end of the chain if needed.
837 */
Paul Bakkere9581d62009-03-28 20:29:25 +0000838 if ( crt->version != 0 && crt->next == NULL)
Paul Bakker320a4b52009-03-28 18:52:39 +0000839 {
840 crt->next = (x509_cert *) malloc( sizeof( x509_cert ) );
841
Paul Bakker7d06ad22009-05-02 15:53:56 +0000842 if( crt->next == NULL )
843 {
Paul Bakker320a4b52009-03-28 18:52:39 +0000844 x509_free( crt );
Paul Bakker7d06ad22009-05-02 15:53:56 +0000845 return( 1 );
846 }
Paul Bakker320a4b52009-03-28 18:52:39 +0000847
Paul Bakker7d06ad22009-05-02 15:53:56 +0000848 crt = crt->next;
849 memset( crt, 0, sizeof( x509_cert ) );
Paul Bakker320a4b52009-03-28 18:52:39 +0000850 }
851
852 /*
Paul Bakker5121ce52009-01-03 21:22:43 +0000853 * check if the certificate is encoded in base64
854 */
855 s1 = (unsigned char *) strstr( (char *) buf,
856 "-----BEGIN CERTIFICATE-----" );
857
858 if( s1 != NULL )
859 {
860 s2 = (unsigned char *) strstr( (char *) buf,
861 "-----END CERTIFICATE-----" );
862
863 if( s2 == NULL || s2 <= s1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000864 return( POLARSSL_ERR_X509_CERT_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +0000865
866 s1 += 27;
867 if( *s1 == '\r' ) s1++;
868 if( *s1 == '\n' ) s1++;
Paul Bakker40e46942009-01-03 21:51:57 +0000869 else return( POLARSSL_ERR_X509_CERT_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +0000870
871 /*
872 * get the DER data length and decode the buffer
873 */
874 len = 0;
875 ret = base64_decode( NULL, &len, s1, s2 - s1 );
876
Paul Bakker40e46942009-01-03 21:51:57 +0000877 if( ret == POLARSSL_ERR_BASE64_INVALID_CHARACTER )
878 return( POLARSSL_ERR_X509_CERT_INVALID_PEM | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000879
880 if( ( p = (unsigned char *) malloc( len ) ) == NULL )
881 return( 1 );
882
883 if( ( ret = base64_decode( p, &len, s1, s2 - s1 ) ) != 0 )
884 {
885 free( p );
Paul Bakker40e46942009-01-03 21:51:57 +0000886 return( POLARSSL_ERR_X509_CERT_INVALID_PEM | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000887 }
888
889 /*
890 * update the buffer size and offset
891 */
892 s2 += 25;
893 if( *s2 == '\r' ) s2++;
894 if( *s2 == '\n' ) s2++;
895 else
896 {
897 free( p );
Paul Bakker40e46942009-01-03 21:51:57 +0000898 return( POLARSSL_ERR_X509_CERT_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +0000899 }
900
901 buflen -= s2 - buf;
902 buf = s2;
903 }
904 else
905 {
906 /*
907 * nope, copy the raw DER data
908 */
909 p = (unsigned char *) malloc( len = buflen );
910
911 if( p == NULL )
912 return( 1 );
913
914 memcpy( p, buf, buflen );
915
916 buflen = 0;
917 }
918
919 crt->raw.p = p;
920 crt->raw.len = len;
921 end = p + len;
922
923 /*
924 * Certificate ::= SEQUENCE {
925 * tbsCertificate TBSCertificate,
926 * signatureAlgorithm AlgorithmIdentifier,
927 * signatureValue BIT STRING }
928 */
929 if( ( ret = asn1_get_tag( &p, end, &len,
930 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
931 {
Paul Bakker7d06ad22009-05-02 15:53:56 +0000932 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000933 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT );
Paul Bakker5121ce52009-01-03 21:22:43 +0000934 }
935
936 if( len != (int) ( end - p ) )
937 {
Paul Bakker7d06ad22009-05-02 15:53:56 +0000938 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000939 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT |
940 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000941 }
942
943 /*
944 * TBSCertificate ::= SEQUENCE {
945 */
946 crt->tbs.p = p;
947
948 if( ( ret = asn1_get_tag( &p, end, &len,
949 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
950 {
Paul Bakker7d06ad22009-05-02 15:53:56 +0000951 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000952 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000953 }
954
955 end = p + len;
956 crt->tbs.len = end - crt->tbs.p;
957
958 /*
959 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
960 *
961 * CertificateSerialNumber ::= INTEGER
962 *
963 * signature AlgorithmIdentifier
964 */
965 if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 ||
966 ( ret = x509_get_serial( &p, end, &crt->serial ) ) != 0 ||
967 ( ret = x509_get_alg( &p, end, &crt->sig_oid1 ) ) != 0 )
968 {
Paul Bakker7d06ad22009-05-02 15:53:56 +0000969 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +0000970 return( ret );
971 }
972
973 crt->version++;
974
975 if( crt->version > 3 )
976 {
Paul Bakker7d06ad22009-05-02 15:53:56 +0000977 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000978 return( POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION );
Paul Bakker5121ce52009-01-03 21:22:43 +0000979 }
980
Paul Bakker27d66162010-03-17 06:56:01 +0000981 if( ( ret = x509_get_sig_alg( &crt->sig_oid1, &crt->sig_alg ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000982 {
Paul Bakker7d06ad22009-05-02 15:53:56 +0000983 x509_free( crt );
Paul Bakker27d66162010-03-17 06:56:01 +0000984 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000985 }
986
987 /*
988 * issuer Name
989 */
990 crt->issuer_raw.p = p;
991
992 if( ( ret = asn1_get_tag( &p, end, &len,
993 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
994 {
Paul Bakker7d06ad22009-05-02 15:53:56 +0000995 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000996 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000997 }
998
999 if( ( ret = x509_get_name( &p, p + len, &crt->issuer ) ) != 0 )
1000 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001001 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001002 return( ret );
1003 }
1004
1005 crt->issuer_raw.len = p - crt->issuer_raw.p;
1006
1007 /*
1008 * Validity ::= SEQUENCE {
1009 * notBefore Time,
1010 * notAfter Time }
1011 *
1012 */
1013 if( ( ret = x509_get_dates( &p, end, &crt->valid_from,
1014 &crt->valid_to ) ) != 0 )
1015 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001016 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001017 return( ret );
1018 }
1019
1020 /*
1021 * subject Name
1022 */
1023 crt->subject_raw.p = p;
1024
1025 if( ( ret = asn1_get_tag( &p, end, &len,
1026 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1027 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001028 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +00001029 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001030 }
1031
1032 if( ( ret = x509_get_name( &p, p + len, &crt->subject ) ) != 0 )
1033 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001034 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001035 return( ret );
1036 }
1037
1038 crt->subject_raw.len = p - crt->subject_raw.p;
1039
1040 /*
1041 * SubjectPublicKeyInfo ::= SEQUENCE
1042 * algorithm AlgorithmIdentifier,
1043 * subjectPublicKey BIT STRING }
1044 */
1045 if( ( ret = asn1_get_tag( &p, end, &len,
1046 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1047 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001048 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +00001049 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001050 }
1051
1052 if( ( ret = x509_get_pubkey( &p, p + len, &crt->pk_oid,
1053 &crt->rsa.N, &crt->rsa.E ) ) != 0 )
1054 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001055 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001056 return( ret );
1057 }
1058
1059 if( ( ret = rsa_check_pubkey( &crt->rsa ) ) != 0 )
1060 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001061 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001062 return( ret );
1063 }
1064
1065 crt->rsa.len = mpi_size( &crt->rsa.N );
1066
1067 /*
1068 * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
1069 * -- If present, version shall be v2 or v3
1070 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
1071 * -- If present, version shall be v2 or v3
1072 * extensions [3] EXPLICIT Extensions OPTIONAL
1073 * -- If present, version shall be v3
1074 */
1075 if( crt->version == 2 || crt->version == 3 )
1076 {
1077 ret = x509_get_uid( &p, end, &crt->issuer_id, 1 );
1078 if( ret != 0 )
1079 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001080 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001081 return( ret );
1082 }
1083 }
1084
1085 if( crt->version == 2 || crt->version == 3 )
1086 {
1087 ret = x509_get_uid( &p, end, &crt->subject_id, 2 );
1088 if( ret != 0 )
1089 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001090 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001091 return( ret );
1092 }
1093 }
1094
1095 if( crt->version == 3 )
1096 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00001097 ret = x509_get_crt_ext( &p, end, &crt->v3_ext,
Paul Bakker5121ce52009-01-03 21:22:43 +00001098 &crt->ca_istrue, &crt->max_pathlen );
1099 if( ret != 0 )
1100 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001101 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001102 return( ret );
1103 }
1104 }
1105
1106 if( p != end )
1107 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001108 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +00001109 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT |
1110 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001111 }
1112
1113 end = crt->raw.p + crt->raw.len;
1114
1115 /*
1116 * signatureAlgorithm AlgorithmIdentifier,
1117 * signatureValue BIT STRING
1118 */
1119 if( ( ret = x509_get_alg( &p, end, &crt->sig_oid2 ) ) != 0 )
1120 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001121 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001122 return( ret );
1123 }
1124
Paul Bakker320a4b52009-03-28 18:52:39 +00001125 if( memcmp( crt->sig_oid1.p, crt->sig_oid2.p, crt->sig_oid1.len ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001126 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001127 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +00001128 return( POLARSSL_ERR_X509_CERT_SIG_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001129 }
1130
1131 if( ( ret = x509_get_sig( &p, end, &crt->sig ) ) != 0 )
1132 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001133 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001134 return( ret );
1135 }
1136
1137 if( p != end )
1138 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001139 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +00001140 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT |
1141 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001142 }
1143
Paul Bakker5121ce52009-01-03 21:22:43 +00001144 if( buflen > 0 )
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
Paul Bakker5121ce52009-01-03 21:22:43 +00001157 return( x509parse_crt( crt, buf, buflen ) );
Paul Bakker320a4b52009-03-28 18:52:39 +00001158 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001159
1160 return( 0 );
1161}
1162
1163/*
Paul Bakkerd98030e2009-05-02 15:13:40 +00001164 * Parse one or more CRLs and add them to the chained list
1165 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001166int x509parse_crl( x509_crl *chain, const unsigned char *buf, int buflen )
Paul Bakkerd98030e2009-05-02 15:13:40 +00001167{
1168 int ret, len;
1169 unsigned char *s1, *s2;
1170 unsigned char *p, *end;
1171 x509_crl *crl;
1172
1173 crl = chain;
1174
1175 /*
1176 * Check for valid input
1177 */
1178 if( crl == NULL || buf == NULL )
1179 return( 1 );
1180
1181 while( crl->version != 0 && crl->next != NULL )
1182 crl = crl->next;
1183
1184 /*
1185 * Add new CRL on the end of the chain if needed.
1186 */
1187 if ( crl->version != 0 && crl->next == NULL)
1188 {
1189 crl->next = (x509_crl *) malloc( sizeof( x509_crl ) );
1190
Paul Bakker7d06ad22009-05-02 15:53:56 +00001191 if( crl->next == NULL )
1192 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00001193 x509_crl_free( crl );
Paul Bakker7d06ad22009-05-02 15:53:56 +00001194 return( 1 );
1195 }
Paul Bakkerd98030e2009-05-02 15:13:40 +00001196
Paul Bakker7d06ad22009-05-02 15:53:56 +00001197 crl = crl->next;
1198 memset( crl, 0, sizeof( x509_crl ) );
Paul Bakkerd98030e2009-05-02 15:13:40 +00001199 }
1200
1201 /*
1202 * check if the CRL is encoded in base64
1203 */
1204 s1 = (unsigned char *) strstr( (char *) buf,
1205 "-----BEGIN X509 CRL-----" );
1206
1207 if( s1 != NULL )
1208 {
1209 s2 = (unsigned char *) strstr( (char *) buf,
1210 "-----END X509 CRL-----" );
1211
1212 if( s2 == NULL || s2 <= s1 )
1213 return( POLARSSL_ERR_X509_CERT_INVALID_PEM );
1214
1215 s1 += 24;
1216 if( *s1 == '\r' ) s1++;
1217 if( *s1 == '\n' ) s1++;
1218 else return( POLARSSL_ERR_X509_CERT_INVALID_PEM );
1219
1220 /*
1221 * get the DER data length and decode the buffer
1222 */
1223 len = 0;
1224 ret = base64_decode( NULL, &len, s1, s2 - s1 );
1225
1226 if( ret == POLARSSL_ERR_BASE64_INVALID_CHARACTER )
1227 return( POLARSSL_ERR_X509_CERT_INVALID_PEM | ret );
1228
1229 if( ( p = (unsigned char *) malloc( len ) ) == NULL )
1230 return( 1 );
1231
1232 if( ( ret = base64_decode( p, &len, s1, s2 - s1 ) ) != 0 )
1233 {
1234 free( p );
1235 return( POLARSSL_ERR_X509_CERT_INVALID_PEM | ret );
1236 }
1237
1238 /*
1239 * update the buffer size and offset
1240 */
1241 s2 += 22;
1242 if( *s2 == '\r' ) s2++;
1243 if( *s2 == '\n' ) s2++;
1244 else
1245 {
1246 free( p );
1247 return( POLARSSL_ERR_X509_CERT_INVALID_PEM );
1248 }
1249
1250 buflen -= s2 - buf;
1251 buf = s2;
1252 }
1253 else
1254 {
1255 /*
1256 * nope, copy the raw DER data
1257 */
1258 p = (unsigned char *) malloc( len = buflen );
1259
1260 if( p == NULL )
1261 return( 1 );
1262
1263 memcpy( p, buf, buflen );
1264
1265 buflen = 0;
1266 }
1267
1268 crl->raw.p = p;
1269 crl->raw.len = len;
1270 end = p + len;
1271
1272 /*
1273 * CertificateList ::= SEQUENCE {
1274 * tbsCertList TBSCertList,
1275 * signatureAlgorithm AlgorithmIdentifier,
1276 * signatureValue BIT STRING }
1277 */
1278 if( ( ret = asn1_get_tag( &p, end, &len,
1279 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1280 {
1281 x509_crl_free( crl );
1282 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT );
1283 }
1284
1285 if( len != (int) ( end - p ) )
1286 {
1287 x509_crl_free( crl );
1288 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT |
1289 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
1290 }
1291
1292 /*
1293 * TBSCertList ::= SEQUENCE {
1294 */
1295 crl->tbs.p = p;
1296
1297 if( ( ret = asn1_get_tag( &p, end, &len,
1298 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1299 {
1300 x509_crl_free( crl );
1301 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
1302 }
1303
1304 end = p + len;
1305 crl->tbs.len = end - crl->tbs.p;
1306
1307 /*
1308 * Version ::= INTEGER OPTIONAL { v1(0), v2(1) }
1309 * -- if present, MUST be v2
1310 *
1311 * signature AlgorithmIdentifier
1312 */
1313 if( ( ret = x509_get_version( &p, end, &crl->version ) ) != 0 ||
1314 ( ret = x509_get_alg( &p, end, &crl->sig_oid1 ) ) != 0 )
1315 {
1316 x509_crl_free( crl );
1317 return( ret );
1318 }
1319
1320 crl->version++;
1321
1322 if( crl->version > 2 )
1323 {
1324 x509_crl_free( crl );
1325 return( POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION );
1326 }
1327
Paul Bakker27d66162010-03-17 06:56:01 +00001328 if( ( ret = x509_get_sig_alg( &crl->sig_oid1, &crl->sig_alg ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +00001329 {
1330 x509_crl_free( crl );
1331 return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
1332 }
1333
1334 /*
1335 * issuer Name
1336 */
1337 crl->issuer_raw.p = p;
1338
1339 if( ( ret = asn1_get_tag( &p, end, &len,
1340 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1341 {
1342 x509_crl_free( crl );
1343 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
1344 }
1345
1346 if( ( ret = x509_get_name( &p, p + len, &crl->issuer ) ) != 0 )
1347 {
1348 x509_crl_free( crl );
1349 return( ret );
1350 }
1351
1352 crl->issuer_raw.len = p - crl->issuer_raw.p;
1353
1354 /*
1355 * thisUpdate Time
1356 * nextUpdate Time OPTIONAL
1357 */
Paul Bakker91200182010-02-18 21:26:15 +00001358 if( ( ret = x509_get_time( &p, end, &crl->this_update ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +00001359 {
1360 x509_crl_free( crl );
1361 return( ret );
1362 }
1363
Paul Bakker91200182010-02-18 21:26:15 +00001364 if( ( ret = x509_get_time( &p, end, &crl->next_update ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +00001365 {
Paul Bakker635f4b42009-07-20 20:34:41 +00001366 if ( ret != ( POLARSSL_ERR_X509_CERT_INVALID_DATE |
Paul Bakker9be19372009-07-27 20:21:53 +00001367 POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) &&
1368 ret != ( POLARSSL_ERR_X509_CERT_INVALID_DATE |
1369 POLARSSL_ERR_ASN1_OUT_OF_DATA ) )
Paul Bakker635f4b42009-07-20 20:34:41 +00001370 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00001371 x509_crl_free( crl );
1372 return( ret );
1373 }
1374 }
1375
1376 /*
1377 * revokedCertificates SEQUENCE OF SEQUENCE {
1378 * userCertificate CertificateSerialNumber,
1379 * revocationDate Time,
1380 * crlEntryExtensions Extensions OPTIONAL
1381 * -- if present, MUST be v2
1382 * } OPTIONAL
1383 */
1384 if( ( ret = x509_get_entries( &p, end, &crl->entry ) ) != 0 )
1385 {
1386 x509_crl_free( crl );
1387 return( ret );
1388 }
1389
1390 /*
1391 * crlExtensions EXPLICIT Extensions OPTIONAL
1392 * -- if present, MUST be v2
1393 */
1394 if( crl->version == 2 )
1395 {
1396 ret = x509_get_crl_ext( &p, end, &crl->crl_ext );
1397
1398 if( ret != 0 )
1399 {
1400 x509_crl_free( crl );
1401 return( ret );
1402 }
1403 }
1404
1405 if( p != end )
1406 {
1407 x509_crl_free( crl );
1408 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT |
1409 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
1410 }
1411
1412 end = crl->raw.p + crl->raw.len;
1413
1414 /*
1415 * signatureAlgorithm AlgorithmIdentifier,
1416 * signatureValue BIT STRING
1417 */
1418 if( ( ret = x509_get_alg( &p, end, &crl->sig_oid2 ) ) != 0 )
1419 {
1420 x509_crl_free( crl );
1421 return( ret );
1422 }
1423
1424 if( memcmp( crl->sig_oid1.p, crl->sig_oid2.p, crl->sig_oid1.len ) != 0 )
1425 {
1426 x509_crl_free( crl );
1427 return( POLARSSL_ERR_X509_CERT_SIG_MISMATCH );
1428 }
1429
1430 if( ( ret = x509_get_sig( &p, end, &crl->sig ) ) != 0 )
1431 {
1432 x509_crl_free( crl );
1433 return( ret );
1434 }
1435
1436 if( p != end )
1437 {
1438 x509_crl_free( crl );
1439 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT |
1440 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
1441 }
1442
1443 if( buflen > 0 )
1444 {
1445 crl->next = (x509_crl *) malloc( sizeof( x509_crl ) );
1446
Paul Bakker7d06ad22009-05-02 15:53:56 +00001447 if( crl->next == NULL )
1448 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00001449 x509_crl_free( crl );
Paul Bakker7d06ad22009-05-02 15:53:56 +00001450 return( 1 );
1451 }
Paul Bakkerd98030e2009-05-02 15:13:40 +00001452
Paul Bakker7d06ad22009-05-02 15:53:56 +00001453 crl = crl->next;
1454 memset( crl, 0, sizeof( x509_crl ) );
Paul Bakkerd98030e2009-05-02 15:13:40 +00001455
1456 return( x509parse_crl( crl, buf, buflen ) );
1457 }
1458
1459 return( 0 );
1460}
1461
1462/*
Paul Bakker2b245eb2009-04-19 18:44:26 +00001463 * Load all data from a file into a given buffer.
1464 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001465int load_file( const char *path, unsigned char **buf, size_t *n )
Paul Bakker2b245eb2009-04-19 18:44:26 +00001466{
Paul Bakkerd98030e2009-05-02 15:13:40 +00001467 FILE *f;
Paul Bakker2b245eb2009-04-19 18:44:26 +00001468
Paul Bakkerd98030e2009-05-02 15:13:40 +00001469 if( ( f = fopen( path, "rb" ) ) == NULL )
1470 return( 1 );
Paul Bakker2b245eb2009-04-19 18:44:26 +00001471
Paul Bakkerd98030e2009-05-02 15:13:40 +00001472 fseek( f, 0, SEEK_END );
1473 *n = (size_t) ftell( f );
1474 fseek( f, 0, SEEK_SET );
Paul Bakker2b245eb2009-04-19 18:44:26 +00001475
Paul Bakkerd98030e2009-05-02 15:13:40 +00001476 if( ( *buf = (unsigned char *) malloc( *n + 1 ) ) == NULL )
1477 return( 1 );
Paul Bakker2b245eb2009-04-19 18:44:26 +00001478
Paul Bakkerd98030e2009-05-02 15:13:40 +00001479 if( fread( *buf, 1, *n, f ) != *n )
1480 {
1481 fclose( f );
1482 free( *buf );
1483 return( 1 );
1484 }
Paul Bakker2b245eb2009-04-19 18:44:26 +00001485
Paul Bakkerd98030e2009-05-02 15:13:40 +00001486 fclose( f );
Paul Bakker2b245eb2009-04-19 18:44:26 +00001487
Paul Bakkerd98030e2009-05-02 15:13:40 +00001488 (*buf)[*n] = '\0';
Paul Bakker2b245eb2009-04-19 18:44:26 +00001489
Paul Bakkerd98030e2009-05-02 15:13:40 +00001490 return( 0 );
Paul Bakker2b245eb2009-04-19 18:44:26 +00001491}
1492
1493/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001494 * Load one or more certificates and add them to the chained list
1495 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001496int x509parse_crtfile( x509_cert *chain, const char *path )
Paul Bakker5121ce52009-01-03 21:22:43 +00001497{
1498 int ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001499 size_t n;
1500 unsigned char *buf;
1501
Paul Bakker2b245eb2009-04-19 18:44:26 +00001502 if ( load_file( path, &buf, &n ) )
Paul Bakker5121ce52009-01-03 21:22:43 +00001503 return( 1 );
1504
Paul Bakker5121ce52009-01-03 21:22:43 +00001505 ret = x509parse_crt( chain, buf, (int) n );
1506
1507 memset( buf, 0, n + 1 );
1508 free( buf );
Paul Bakker5121ce52009-01-03 21:22:43 +00001509
1510 return( ret );
1511}
1512
Paul Bakkerd98030e2009-05-02 15:13:40 +00001513/*
1514 * Load one or more CRLs and add them to the chained list
1515 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001516int x509parse_crlfile( x509_crl *chain, const char *path )
Paul Bakkerd98030e2009-05-02 15:13:40 +00001517{
1518 int ret;
1519 size_t n;
1520 unsigned char *buf;
1521
1522 if ( load_file( path, &buf, &n ) )
1523 return( 1 );
1524
1525 ret = x509parse_crl( chain, buf, (int) n );
1526
1527 memset( buf, 0, n + 1 );
1528 free( buf );
1529
1530 return( ret );
1531}
1532
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00001533#if defined(POLARSSL_DES_C) && defined(POLARSSL_MD5_C)
Paul Bakker5121ce52009-01-03 21:22:43 +00001534/*
1535 * Read a 16-byte hex string and convert it to binary
1536 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001537static int x509_get_iv( const unsigned char *s, unsigned char iv[8] )
Paul Bakker5121ce52009-01-03 21:22:43 +00001538{
1539 int i, j, k;
1540
1541 memset( iv, 0, 8 );
1542
1543 for( i = 0; i < 16; i++, s++ )
1544 {
1545 if( *s >= '0' && *s <= '9' ) j = *s - '0'; else
1546 if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else
1547 if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else
Paul Bakker40e46942009-01-03 21:51:57 +00001548 return( POLARSSL_ERR_X509_KEY_INVALID_ENC_IV );
Paul Bakker5121ce52009-01-03 21:22:43 +00001549
1550 k = ( ( i & 1 ) != 0 ) ? j : j << 4;
1551
1552 iv[i >> 1] = (unsigned char)( iv[i >> 1] | k );
1553 }
1554
1555 return( 0 );
1556}
1557
1558/*
1559 * Decrypt with 3DES-CBC, using PBKDF1 for key derivation
1560 */
1561static void x509_des3_decrypt( unsigned char des3_iv[8],
1562 unsigned char *buf, int buflen,
Paul Bakkerff60ee62010-03-16 21:09:09 +00001563 const unsigned char *pwd, int pwdlen )
Paul Bakker5121ce52009-01-03 21:22:43 +00001564{
1565 md5_context md5_ctx;
1566 des3_context des3_ctx;
1567 unsigned char md5sum[16];
1568 unsigned char des3_key[24];
1569
1570 /*
1571 * 3DES key[ 0..15] = MD5(pwd || IV)
1572 * key[16..23] = MD5(pwd || IV || 3DES key[ 0..15])
1573 */
1574 md5_starts( &md5_ctx );
1575 md5_update( &md5_ctx, pwd, pwdlen );
1576 md5_update( &md5_ctx, des3_iv, 8 );
1577 md5_finish( &md5_ctx, md5sum );
1578 memcpy( des3_key, md5sum, 16 );
1579
1580 md5_starts( &md5_ctx );
1581 md5_update( &md5_ctx, md5sum, 16 );
1582 md5_update( &md5_ctx, pwd, pwdlen );
1583 md5_update( &md5_ctx, des3_iv, 8 );
1584 md5_finish( &md5_ctx, md5sum );
1585 memcpy( des3_key + 16, md5sum, 8 );
1586
1587 des3_set3key_dec( &des3_ctx, des3_key );
1588 des3_crypt_cbc( &des3_ctx, DES_DECRYPT, buflen,
1589 des3_iv, buf, buf );
1590
1591 memset( &md5_ctx, 0, sizeof( md5_ctx ) );
1592 memset( &des3_ctx, 0, sizeof( des3_ctx ) );
1593 memset( md5sum, 0, 16 );
1594 memset( des3_key, 0, 24 );
1595}
1596#endif
1597
1598/*
1599 * Parse a private RSA key
1600 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001601int x509parse_key( rsa_context *rsa, const unsigned char *key, int keylen,
1602 const unsigned char *pwd, int pwdlen )
Paul Bakker5121ce52009-01-03 21:22:43 +00001603{
1604 int ret, len, enc;
Paul Bakkerff60ee62010-03-16 21:09:09 +00001605 unsigned char *buf, *s1, *s2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001606 unsigned char *p, *end;
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00001607#if defined(POLARSSL_DES_C) && defined(POLARSSL_MD5_C)
Paul Bakker5121ce52009-01-03 21:22:43 +00001608 unsigned char des3_iv[8];
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00001609#else
1610 ((void) pwd);
1611 ((void) pwdlen);
1612#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00001613
Paul Bakkerff60ee62010-03-16 21:09:09 +00001614 s1 = (unsigned char *) strstr( (char *) key,
Paul Bakker5121ce52009-01-03 21:22:43 +00001615 "-----BEGIN RSA PRIVATE KEY-----" );
1616
1617 if( s1 != NULL )
1618 {
Paul Bakkerff60ee62010-03-16 21:09:09 +00001619 s2 = (unsigned char *) strstr( (char *) key,
Paul Bakker5121ce52009-01-03 21:22:43 +00001620 "-----END RSA PRIVATE KEY-----" );
1621
1622 if( s2 == NULL || s2 <= s1 )
Paul Bakker40e46942009-01-03 21:51:57 +00001623 return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001624
1625 s1 += 31;
1626 if( *s1 == '\r' ) s1++;
1627 if( *s1 == '\n' ) s1++;
Paul Bakker40e46942009-01-03 21:51:57 +00001628 else return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001629
1630 enc = 0;
1631
1632 if( memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 )
1633 {
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00001634#if defined(POLARSSL_DES_C) && defined(POLARSSL_MD5_C)
Paul Bakker5121ce52009-01-03 21:22:43 +00001635 enc++;
1636
1637 s1 += 22;
1638 if( *s1 == '\r' ) s1++;
1639 if( *s1 == '\n' ) s1++;
Paul Bakker40e46942009-01-03 21:51:57 +00001640 else return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001641
1642 if( memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001643 return( POLARSSL_ERR_X509_KEY_UNKNOWN_ENC_ALG );
Paul Bakker5121ce52009-01-03 21:22:43 +00001644
1645 s1 += 23;
1646 if( x509_get_iv( s1, des3_iv ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001647 return( POLARSSL_ERR_X509_KEY_INVALID_ENC_IV );
Paul Bakker5121ce52009-01-03 21:22:43 +00001648
1649 s1 += 16;
1650 if( *s1 == '\r' ) s1++;
1651 if( *s1 == '\n' ) s1++;
Paul Bakker40e46942009-01-03 21:51:57 +00001652 else return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001653#else
Paul Bakker40e46942009-01-03 21:51:57 +00001654 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001655#endif
1656 }
1657
1658 len = 0;
1659 ret = base64_decode( NULL, &len, s1, s2 - s1 );
1660
Paul Bakker40e46942009-01-03 21:51:57 +00001661 if( ret == POLARSSL_ERR_BASE64_INVALID_CHARACTER )
1662 return( ret | POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001663
1664 if( ( buf = (unsigned char *) malloc( len ) ) == NULL )
1665 return( 1 );
1666
1667 if( ( ret = base64_decode( buf, &len, s1, s2 - s1 ) ) != 0 )
1668 {
1669 free( buf );
Paul Bakker40e46942009-01-03 21:51:57 +00001670 return( ret | POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001671 }
1672
Paul Bakkerff60ee62010-03-16 21:09:09 +00001673 keylen = len;
Paul Bakker5121ce52009-01-03 21:22:43 +00001674
1675 if( enc != 0 )
1676 {
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00001677#if defined(POLARSSL_DES_C) && defined(POLARSSL_MD5_C)
Paul Bakker5121ce52009-01-03 21:22:43 +00001678 if( pwd == NULL )
1679 {
1680 free( buf );
Paul Bakker40e46942009-01-03 21:51:57 +00001681 return( POLARSSL_ERR_X509_KEY_PASSWORD_REQUIRED );
Paul Bakker5121ce52009-01-03 21:22:43 +00001682 }
1683
Paul Bakkerff60ee62010-03-16 21:09:09 +00001684 x509_des3_decrypt( des3_iv, buf, keylen, pwd, pwdlen );
Paul Bakker5121ce52009-01-03 21:22:43 +00001685
1686 if( buf[0] != 0x30 || buf[1] != 0x82 ||
1687 buf[4] != 0x02 || buf[5] != 0x01 )
1688 {
1689 free( buf );
Paul Bakker40e46942009-01-03 21:51:57 +00001690 return( POLARSSL_ERR_X509_KEY_PASSWORD_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001691 }
1692#else
Paul Bakker40e46942009-01-03 21:51:57 +00001693 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001694#endif
1695 }
1696 }
Paul Bakkerff60ee62010-03-16 21:09:09 +00001697 else
1698 {
1699 buf = NULL;
1700 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001701
1702 memset( rsa, 0, sizeof( rsa_context ) );
1703
Paul Bakkerff60ee62010-03-16 21:09:09 +00001704 p = ( s1 != NULL ) ? buf : (unsigned char *) key;
1705 end = p + keylen;
Paul Bakker5121ce52009-01-03 21:22:43 +00001706
1707 /*
1708 * RSAPrivateKey ::= SEQUENCE {
1709 * version Version,
1710 * modulus INTEGER, -- n
1711 * publicExponent INTEGER, -- e
1712 * privateExponent INTEGER, -- d
1713 * prime1 INTEGER, -- p
1714 * prime2 INTEGER, -- q
1715 * exponent1 INTEGER, -- d mod (p-1)
1716 * exponent2 INTEGER, -- d mod (q-1)
1717 * coefficient INTEGER, -- (inverse of q) mod p
1718 * otherPrimeInfos OtherPrimeInfos OPTIONAL
1719 * }
1720 */
1721 if( ( ret = asn1_get_tag( &p, end, &len,
1722 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1723 {
1724 if( s1 != NULL )
1725 free( buf );
1726
1727 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001728 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001729 }
1730
1731 end = p + len;
1732
1733 if( ( ret = asn1_get_int( &p, end, &rsa->ver ) ) != 0 )
1734 {
1735 if( s1 != NULL )
1736 free( buf );
1737
1738 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001739 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001740 }
1741
1742 if( rsa->ver != 0 )
1743 {
1744 if( s1 != NULL )
1745 free( buf );
1746
1747 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001748 return( ret | POLARSSL_ERR_X509_KEY_INVALID_VERSION );
Paul Bakker5121ce52009-01-03 21:22:43 +00001749 }
1750
1751 if( ( ret = asn1_get_mpi( &p, end, &rsa->N ) ) != 0 ||
1752 ( ret = asn1_get_mpi( &p, end, &rsa->E ) ) != 0 ||
1753 ( ret = asn1_get_mpi( &p, end, &rsa->D ) ) != 0 ||
1754 ( ret = asn1_get_mpi( &p, end, &rsa->P ) ) != 0 ||
1755 ( ret = asn1_get_mpi( &p, end, &rsa->Q ) ) != 0 ||
1756 ( ret = asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 ||
1757 ( ret = asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 ||
1758 ( ret = asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 )
1759 {
1760 if( s1 != NULL )
1761 free( buf );
1762
1763 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001764 return( ret | POLARSSL_ERR_X509_KEY_INVALID_FORMAT );
Paul Bakker5121ce52009-01-03 21:22:43 +00001765 }
1766
1767 rsa->len = mpi_size( &rsa->N );
1768
1769 if( p != end )
1770 {
1771 if( s1 != NULL )
1772 free( buf );
1773
1774 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001775 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT |
1776 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001777 }
1778
1779 if( ( ret = rsa_check_privkey( rsa ) ) != 0 )
1780 {
1781 if( s1 != NULL )
1782 free( buf );
1783
1784 rsa_free( rsa );
1785 return( ret );
1786 }
1787
1788 if( s1 != NULL )
1789 free( buf );
1790
1791 return( 0 );
1792}
1793
1794/*
1795 * Load and parse a private RSA key
1796 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001797int x509parse_keyfile( rsa_context *rsa, const char *path, const char *pwd )
Paul Bakker5121ce52009-01-03 21:22:43 +00001798{
1799 int ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001800 size_t n;
1801 unsigned char *buf;
1802
Paul Bakker2b245eb2009-04-19 18:44:26 +00001803 if ( load_file( path, &buf, &n ) )
Paul Bakker5121ce52009-01-03 21:22:43 +00001804 return( 1 );
1805
Paul Bakker5121ce52009-01-03 21:22:43 +00001806 if( pwd == NULL )
1807 ret = x509parse_key( rsa, buf, (int) n, NULL, 0 );
1808 else
1809 ret = x509parse_key( rsa, buf, (int) n,
1810 (unsigned char *) pwd, strlen( pwd ) );
1811
1812 memset( buf, 0, n + 1 );
1813 free( buf );
Paul Bakker5121ce52009-01-03 21:22:43 +00001814
1815 return( ret );
1816}
1817
1818#if defined _MSC_VER && !defined snprintf
Paul Bakkerd98030e2009-05-02 15:13:40 +00001819#include <stdarg.h>
1820
1821#if !defined vsnprintf
1822#define vsnprintf _vsnprintf
1823#endif // vsnprintf
1824
1825/*
1826 * Windows _snprintf and _vsnprintf are not compatible to linux versions.
1827 * Result value is not size of buffer needed, but -1 if no fit is possible.
1828 *
1829 * This fuction tries to 'fix' this by at least suggesting enlarging the
1830 * size by 20.
1831 */
1832int compat_snprintf(char *str, size_t size, const char *format, ...)
1833{
1834 va_list ap;
1835 int res = -1;
1836
1837 va_start( ap, format );
1838
1839 res = vsnprintf( str, size, format, ap );
1840
1841 va_end( ap );
1842
1843 // No quick fix possible
1844 if ( res < 0 )
1845 return( size + 20 );
1846
1847 return res;
1848}
1849
1850#define snprintf compat_snprintf
Paul Bakker5121ce52009-01-03 21:22:43 +00001851#endif
1852
Paul Bakkerd98030e2009-05-02 15:13:40 +00001853#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL -2
1854
1855#define SAFE_SNPRINTF() \
1856{ \
1857 if( ret == -1 ) \
1858 return( -1 ); \
1859 \
1860 if ( ret > n ) { \
1861 p[n - 1] = '\0'; \
1862 return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
1863 } \
1864 \
1865 n -= ret; \
1866 p += ret; \
1867}
1868
Paul Bakker5121ce52009-01-03 21:22:43 +00001869/*
1870 * Store the name in printable form into buf; no more
Paul Bakkerd98030e2009-05-02 15:13:40 +00001871 * than size characters will be written
Paul Bakker5121ce52009-01-03 21:22:43 +00001872 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001873int x509parse_dn_gets( char *buf, size_t size, const x509_name *dn )
Paul Bakker5121ce52009-01-03 21:22:43 +00001874{
Paul Bakkerd98030e2009-05-02 15:13:40 +00001875 int i, ret, n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001876 unsigned char c;
Paul Bakkerff60ee62010-03-16 21:09:09 +00001877 const x509_name *name;
Paul Bakker5121ce52009-01-03 21:22:43 +00001878 char s[128], *p;
1879
1880 memset( s, 0, sizeof( s ) );
1881
1882 name = dn;
1883 p = buf;
Paul Bakkerd98030e2009-05-02 15:13:40 +00001884 n = size;
Paul Bakker5121ce52009-01-03 21:22:43 +00001885
1886 while( name != NULL )
1887 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00001888 if( name != dn ) {
1889 ret = snprintf( p, n, ", " );
1890 SAFE_SNPRINTF();
1891 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001892
1893 if( memcmp( name->oid.p, OID_X520, 2 ) == 0 )
1894 {
1895 switch( name->oid.p[2] )
1896 {
1897 case X520_COMMON_NAME:
Paul Bakkerd98030e2009-05-02 15:13:40 +00001898 ret = snprintf( p, n, "CN=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00001899
1900 case X520_COUNTRY:
Paul Bakkerd98030e2009-05-02 15:13:40 +00001901 ret = snprintf( p, n, "C=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00001902
1903 case X520_LOCALITY:
Paul Bakkerd98030e2009-05-02 15:13:40 +00001904 ret = snprintf( p, n, "L=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00001905
1906 case X520_STATE:
Paul Bakkerd98030e2009-05-02 15:13:40 +00001907 ret = snprintf( p, n, "ST=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00001908
1909 case X520_ORGANIZATION:
Paul Bakkerd98030e2009-05-02 15:13:40 +00001910 ret = snprintf( p, n, "O=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00001911
1912 case X520_ORG_UNIT:
Paul Bakkerd98030e2009-05-02 15:13:40 +00001913 ret = snprintf( p, n, "OU=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00001914
1915 default:
Paul Bakkerd98030e2009-05-02 15:13:40 +00001916 ret = snprintf( p, n, "0x%02X=",
Paul Bakker5121ce52009-01-03 21:22:43 +00001917 name->oid.p[2] );
1918 break;
1919 }
Paul Bakkerd98030e2009-05-02 15:13:40 +00001920 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00001921 }
1922 else if( memcmp( name->oid.p, OID_PKCS9, 8 ) == 0 )
1923 {
1924 switch( name->oid.p[8] )
1925 {
1926 case PKCS9_EMAIL:
Paul Bakkerd98030e2009-05-02 15:13:40 +00001927 ret = snprintf( p, n, "emailAddress=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00001928
1929 default:
Paul Bakkerd98030e2009-05-02 15:13:40 +00001930 ret = snprintf( p, n, "0x%02X=",
Paul Bakker5121ce52009-01-03 21:22:43 +00001931 name->oid.p[8] );
1932 break;
1933 }
Paul Bakkerd98030e2009-05-02 15:13:40 +00001934 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00001935 }
1936 else
Paul Bakkerd98030e2009-05-02 15:13:40 +00001937 {
1938 ret = snprintf( p, n, "\?\?=" );
1939 SAFE_SNPRINTF();
1940 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001941
1942 for( i = 0; i < name->val.len; i++ )
1943 {
1944 if( i >= (int) sizeof( s ) - 1 )
1945 break;
1946
1947 c = name->val.p[i];
1948 if( c < 32 || c == 127 || ( c > 128 && c < 160 ) )
1949 s[i] = '?';
1950 else s[i] = c;
1951 }
1952 s[i] = '\0';
Paul Bakkerd98030e2009-05-02 15:13:40 +00001953 ret = snprintf( p, n, "%s", s );
1954 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00001955 name = name->next;
1956 }
1957
Paul Bakkerd98030e2009-05-02 15:13:40 +00001958 return( size - n );
Paul Bakker5121ce52009-01-03 21:22:43 +00001959}
1960
1961/*
Paul Bakkerd98030e2009-05-02 15:13:40 +00001962 * Return an informational string about the certificate.
Paul Bakker5121ce52009-01-03 21:22:43 +00001963 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001964int x509parse_cert_info( char *buf, size_t size, const char *prefix,
1965 const x509_cert *crt )
Paul Bakker5121ce52009-01-03 21:22:43 +00001966{
Paul Bakkerd98030e2009-05-02 15:13:40 +00001967 int i, n, nr, ret;
1968 char *p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001969
1970 p = buf;
Paul Bakkerd98030e2009-05-02 15:13:40 +00001971 n = size;
Paul Bakker5121ce52009-01-03 21:22:43 +00001972
Paul Bakkerd98030e2009-05-02 15:13:40 +00001973 ret = snprintf( p, n, "%scert. version : %d\n",
Paul Bakker5121ce52009-01-03 21:22:43 +00001974 prefix, crt->version );
Paul Bakkerd98030e2009-05-02 15:13:40 +00001975 SAFE_SNPRINTF();
1976 ret = snprintf( p, n, "%sserial number : ",
Paul Bakker5121ce52009-01-03 21:22:43 +00001977 prefix );
Paul Bakkerd98030e2009-05-02 15:13:40 +00001978 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00001979
Paul Bakkerd98030e2009-05-02 15:13:40 +00001980 nr = ( crt->serial.len <= 32 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001981 ? crt->serial.len : 32;
1982
Paul Bakkerd98030e2009-05-02 15:13:40 +00001983 for( i = 0; i < nr; i++ )
1984 {
1985 ret = snprintf( p, n, "%02X%s",
1986 crt->serial.p[i], ( i < nr - 1 ) ? ":" : "" );
1987 SAFE_SNPRINTF();
1988 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001989
Paul Bakkerd98030e2009-05-02 15:13:40 +00001990 ret = snprintf( p, n, "\n%sissuer name : ", prefix );
1991 SAFE_SNPRINTF();
1992 ret = x509parse_dn_gets( p, n, &crt->issuer );
1993 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00001994
Paul Bakkerd98030e2009-05-02 15:13:40 +00001995 ret = snprintf( p, n, "\n%ssubject name : ", prefix );
1996 SAFE_SNPRINTF();
1997 ret = x509parse_dn_gets( p, n, &crt->subject );
1998 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00001999
Paul Bakkerd98030e2009-05-02 15:13:40 +00002000 ret = snprintf( p, n, "\n%sissued on : " \
Paul Bakker5121ce52009-01-03 21:22:43 +00002001 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
2002 crt->valid_from.year, crt->valid_from.mon,
2003 crt->valid_from.day, crt->valid_from.hour,
2004 crt->valid_from.min, crt->valid_from.sec );
Paul Bakkerd98030e2009-05-02 15:13:40 +00002005 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002006
Paul Bakkerd98030e2009-05-02 15:13:40 +00002007 ret = snprintf( p, n, "\n%sexpires on : " \
Paul Bakker5121ce52009-01-03 21:22:43 +00002008 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
2009 crt->valid_to.year, crt->valid_to.mon,
2010 crt->valid_to.day, crt->valid_to.hour,
2011 crt->valid_to.min, crt->valid_to.sec );
Paul Bakkerd98030e2009-05-02 15:13:40 +00002012 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002013
Paul Bakkerd98030e2009-05-02 15:13:40 +00002014 ret = snprintf( p, n, "\n%ssigned using : RSA+", prefix );
2015 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002016
Paul Bakker27d66162010-03-17 06:56:01 +00002017 switch( crt->sig_alg )
Paul Bakker5121ce52009-01-03 21:22:43 +00002018 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00002019 case SIG_RSA_MD2 : ret = snprintf( p, n, "MD2" ); break;
2020 case SIG_RSA_MD4 : ret = snprintf( p, n, "MD4" ); break;
2021 case SIG_RSA_MD5 : ret = snprintf( p, n, "MD5" ); break;
2022 case SIG_RSA_SHA1 : ret = snprintf( p, n, "SHA1" ); break;
2023 case SIG_RSA_SHA224 : ret = snprintf( p, n, "SHA224" ); break;
2024 case SIG_RSA_SHA256 : ret = snprintf( p, n, "SHA256" ); break;
2025 case SIG_RSA_SHA384 : ret = snprintf( p, n, "SHA384" ); break;
2026 case SIG_RSA_SHA512 : ret = snprintf( p, n, "SHA512" ); break;
2027 default: ret = snprintf( p, n, "???" ); break;
2028 }
2029 SAFE_SNPRINTF();
2030
2031 ret = snprintf( p, n, "\n%sRSA key size : %d bits\n", prefix,
2032 crt->rsa.N.n * (int) sizeof( unsigned long ) * 8 );
2033 SAFE_SNPRINTF();
2034
2035 return( size - n );
2036}
2037
2038/*
2039 * Return an informational string about the CRL.
2040 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00002041int x509parse_crl_info( char *buf, size_t size, const char *prefix,
2042 const x509_crl *crl )
Paul Bakkerd98030e2009-05-02 15:13:40 +00002043{
2044 int i, n, nr, ret;
2045 char *p;
Paul Bakkerff60ee62010-03-16 21:09:09 +00002046 const x509_crl_entry *entry;
Paul Bakkerd98030e2009-05-02 15:13:40 +00002047
2048 p = buf;
2049 n = size;
2050
2051 ret = snprintf( p, n, "%sCRL version : %d",
2052 prefix, crl->version );
2053 SAFE_SNPRINTF();
2054
2055 ret = snprintf( p, n, "\n%sissuer name : ", prefix );
2056 SAFE_SNPRINTF();
2057 ret = x509parse_dn_gets( p, n, &crl->issuer );
2058 SAFE_SNPRINTF();
2059
2060 ret = snprintf( p, n, "\n%sthis update : " \
2061 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
2062 crl->this_update.year, crl->this_update.mon,
2063 crl->this_update.day, crl->this_update.hour,
2064 crl->this_update.min, crl->this_update.sec );
2065 SAFE_SNPRINTF();
2066
2067 ret = snprintf( p, n, "\n%snext update : " \
2068 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
2069 crl->next_update.year, crl->next_update.mon,
2070 crl->next_update.day, crl->next_update.hour,
2071 crl->next_update.min, crl->next_update.sec );
2072 SAFE_SNPRINTF();
2073
2074 entry = &crl->entry;
2075
2076 ret = snprintf( p, n, "\n%sRevoked certificates:",
2077 prefix );
2078 SAFE_SNPRINTF();
2079
Paul Bakker9be19372009-07-27 20:21:53 +00002080 while( entry != NULL && entry->raw.len != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +00002081 {
2082 ret = snprintf( p, n, "\n%sserial number: ",
2083 prefix );
2084 SAFE_SNPRINTF();
2085
2086 nr = ( entry->serial.len <= 32 )
2087 ? entry->serial.len : 32;
2088
2089 for( i = 0; i < nr; i++ ) {
2090 ret = snprintf( p, n, "%02X%s",
2091 entry->serial.p[i], ( i < nr - 1 ) ? ":" : "" );
2092 SAFE_SNPRINTF();
2093 }
2094
2095 ret = snprintf( p, n, " revocation date: " \
2096 "%04d-%02d-%02d %02d:%02d:%02d",
2097 entry->revocation_date.year, entry->revocation_date.mon,
2098 entry->revocation_date.day, entry->revocation_date.hour,
2099 entry->revocation_date.min, entry->revocation_date.sec );
2100 SAFE_SNPRINTF();
2101
2102 entry = entry->next;
Paul Bakker5121ce52009-01-03 21:22:43 +00002103 }
2104
Paul Bakkerd98030e2009-05-02 15:13:40 +00002105 ret = snprintf( p, n, "\n%ssigned using : RSA+", prefix );
2106 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002107
Paul Bakker27d66162010-03-17 06:56:01 +00002108 switch( crl->sig_alg )
Paul Bakkerd98030e2009-05-02 15:13:40 +00002109 {
2110 case SIG_RSA_MD2 : ret = snprintf( p, n, "MD2" ); break;
2111 case SIG_RSA_MD4 : ret = snprintf( p, n, "MD4" ); break;
2112 case SIG_RSA_MD5 : ret = snprintf( p, n, "MD5" ); break;
2113 case SIG_RSA_SHA1 : ret = snprintf( p, n, "SHA1" ); break;
2114 case SIG_RSA_SHA224 : ret = snprintf( p, n, "SHA224" ); break;
2115 case SIG_RSA_SHA256 : ret = snprintf( p, n, "SHA256" ); break;
2116 case SIG_RSA_SHA384 : ret = snprintf( p, n, "SHA384" ); break;
2117 case SIG_RSA_SHA512 : ret = snprintf( p, n, "SHA512" ); break;
2118 default: ret = snprintf( p, n, "???" ); break;
2119 }
2120 SAFE_SNPRINTF();
2121
Paul Bakker1e27bb22009-07-19 20:25:25 +00002122 ret = snprintf( p, n, "\n" );
2123 SAFE_SNPRINTF();
2124
Paul Bakkerd98030e2009-05-02 15:13:40 +00002125 return( size - n );
Paul Bakker5121ce52009-01-03 21:22:43 +00002126}
2127
2128/*
Paul Bakker40ea7de2009-05-03 10:18:48 +00002129 * Return 0 if the x509_time is still valid, or 1 otherwise.
Paul Bakker5121ce52009-01-03 21:22:43 +00002130 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00002131int x509parse_time_expired( const x509_time *to )
Paul Bakker5121ce52009-01-03 21:22:43 +00002132{
2133 struct tm *lt;
2134 time_t tt;
2135
2136 tt = time( NULL );
2137 lt = localtime( &tt );
2138
Paul Bakker40ea7de2009-05-03 10:18:48 +00002139 if( lt->tm_year > to->year - 1900 )
2140 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002141
Paul Bakker40ea7de2009-05-03 10:18:48 +00002142 if( lt->tm_year == to->year - 1900 &&
2143 lt->tm_mon > to->mon - 1 )
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 lt->tm_mday > to->day )
2149 return( 1 );
2150
2151 return( 0 );
2152}
2153
2154/*
2155 * Return 1 if the certificate is revoked, or 0 otherwise.
2156 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00002157int x509parse_revoked( const x509_cert *crt, const x509_crl *crl )
Paul Bakker40ea7de2009-05-03 10:18:48 +00002158{
Paul Bakkerff60ee62010-03-16 21:09:09 +00002159 const x509_crl_entry *cur = &crl->entry;
Paul Bakker40ea7de2009-05-03 10:18:48 +00002160
2161 while( cur != NULL && cur->serial.len != 0 )
2162 {
2163 if( memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 )
2164 {
2165 if( x509parse_time_expired( &cur->revocation_date ) )
2166 return( 1 );
2167 }
2168
2169 cur = cur->next;
2170 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002171
2172 return( 0 );
2173}
2174
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002175/*
2176 * Wrapper for x509 hashes.
2177 *
2178 * @param out Buffer to receive the hash (Should be at least 64 bytes)
2179 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00002180static void x509_hash( const unsigned char *in, int len, int alg,
Paul Bakker5121ce52009-01-03 21:22:43 +00002181 unsigned char *out )
2182{
2183 switch( alg )
2184 {
Paul Bakker40e46942009-01-03 21:51:57 +00002185#if defined(POLARSSL_MD2_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00002186 case SIG_RSA_MD2 : md2( in, len, out ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002187#endif
Paul Bakker40e46942009-01-03 21:51:57 +00002188#if defined(POLARSSL_MD4_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00002189 case SIG_RSA_MD4 : md4( in, len, out ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002190#endif
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002191#if defined(POLARSSL_MD5_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00002192 case SIG_RSA_MD5 : md5( in, len, out ); break;
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002193#endif
2194#if defined(POLARSSL_SHA1_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00002195 case SIG_RSA_SHA1 : sha1( in, len, out ); break;
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002196#endif
Paul Bakker4593aea2009-02-09 22:32:35 +00002197#if defined(POLARSSL_SHA2_C)
2198 case SIG_RSA_SHA224 : sha2( in, len, out, 1 ); break;
2199 case SIG_RSA_SHA256 : sha2( in, len, out, 0 ); break;
2200#endif
Paul Bakkerfe1aea72009-10-03 20:09:14 +00002201#if defined(POLARSSL_SHA4_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00002202 case SIG_RSA_SHA384 : sha4( in, len, out, 1 ); break;
2203 case SIG_RSA_SHA512 : sha4( in, len, out, 0 ); break;
2204#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00002205 default:
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002206 memset( out, '\xFF', 64 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002207 break;
2208 }
2209}
2210
2211/*
2212 * Verify the certificate validity
2213 */
2214int x509parse_verify( x509_cert *crt,
2215 x509_cert *trust_ca,
Paul Bakker40ea7de2009-05-03 10:18:48 +00002216 x509_crl *ca_crl,
Paul Bakkerff60ee62010-03-16 21:09:09 +00002217 const char *cn, int *flags )
Paul Bakker5121ce52009-01-03 21:22:43 +00002218{
2219 int cn_len;
2220 int hash_id;
2221 int pathlen;
2222 x509_cert *cur;
2223 x509_name *name;
Paul Bakker4593aea2009-02-09 22:32:35 +00002224 unsigned char hash[64];
Paul Bakker5121ce52009-01-03 21:22:43 +00002225
Paul Bakker40ea7de2009-05-03 10:18:48 +00002226 *flags = 0;
2227
2228 if( x509parse_time_expired( &crt->valid_to ) )
2229 *flags = BADCERT_EXPIRED;
Paul Bakker5121ce52009-01-03 21:22:43 +00002230
2231 if( cn != NULL )
2232 {
2233 name = &crt->subject;
2234 cn_len = strlen( cn );
2235
2236 while( name != NULL )
2237 {
2238 if( memcmp( name->oid.p, OID_CN, 3 ) == 0 &&
2239 memcmp( name->val.p, cn, cn_len ) == 0 &&
2240 name->val.len == cn_len )
2241 break;
2242
2243 name = name->next;
2244 }
2245
2246 if( name == NULL )
2247 *flags |= BADCERT_CN_MISMATCH;
2248 }
2249
2250 *flags |= BADCERT_NOT_TRUSTED;
2251
2252 /*
2253 * Iterate upwards in the given cert chain,
2254 * ignoring any upper cert with CA != TRUE.
2255 */
2256 cur = crt->next;
2257
2258 pathlen = 1;
2259
Paul Bakker7c6d4a42009-03-28 20:35:47 +00002260 while( cur != NULL && cur->version != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002261 {
2262 if( cur->ca_istrue == 0 ||
2263 crt->issuer_raw.len != cur->subject_raw.len ||
2264 memcmp( crt->issuer_raw.p, cur->subject_raw.p,
2265 crt->issuer_raw.len ) != 0 )
2266 {
2267 cur = cur->next;
2268 continue;
2269 }
2270
Paul Bakker27d66162010-03-17 06:56:01 +00002271 hash_id = crt->sig_alg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002272
2273 x509_hash( crt->tbs.p, crt->tbs.len, hash_id, hash );
2274
2275 if( rsa_pkcs1_verify( &cur->rsa, RSA_PUBLIC, hash_id,
2276 0, hash, crt->sig.p ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00002277 return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +00002278
2279 pathlen++;
2280
2281 crt = cur;
2282 cur = crt->next;
2283 }
2284
2285 /*
2286 * Atempt to validate topmost cert with our CA chain.
2287 */
Paul Bakker7c6d4a42009-03-28 20:35:47 +00002288 while( trust_ca != NULL && trust_ca->version != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002289 {
2290 if( crt->issuer_raw.len != trust_ca->subject_raw.len ||
2291 memcmp( crt->issuer_raw.p, trust_ca->subject_raw.p,
2292 crt->issuer_raw.len ) != 0 )
2293 {
2294 trust_ca = trust_ca->next;
2295 continue;
2296 }
2297
2298 if( trust_ca->max_pathlen > 0 &&
2299 trust_ca->max_pathlen < pathlen )
2300 break;
2301
Paul Bakker27d66162010-03-17 06:56:01 +00002302 hash_id = crt->sig_alg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002303
2304 x509_hash( crt->tbs.p, crt->tbs.len, hash_id, hash );
2305
2306 if( rsa_pkcs1_verify( &trust_ca->rsa, RSA_PUBLIC, hash_id,
2307 0, hash, crt->sig.p ) == 0 )
2308 {
2309 /*
2310 * cert. is signed by a trusted CA
2311 */
2312 *flags &= ~BADCERT_NOT_TRUSTED;
2313 break;
2314 }
2315
2316 trust_ca = trust_ca->next;
2317 }
2318
Paul Bakker40ea7de2009-05-03 10:18:48 +00002319 /*
2320 * TODO: What happens if no CRL is present?
2321 * Suggestion: Revocation state should be unknown if no CRL is present.
2322 * For backwards compatibility this is not yet implemented.
2323 */
2324
2325 /*
2326 * Check if the topmost certificate is revoked if the trusted CA is
2327 * determined.
2328 */
2329 while( trust_ca != NULL && ca_crl != NULL && ca_crl->version != 0 )
2330 {
2331 if( ca_crl->issuer_raw.len != trust_ca->subject_raw.len ||
2332 memcmp( ca_crl->issuer_raw.p, trust_ca->subject_raw.p,
2333 ca_crl->issuer_raw.len ) != 0 )
2334 {
2335 ca_crl = ca_crl->next;
2336 continue;
2337 }
2338
2339 /*
2340 * Check if CRL is correctry signed by the trusted CA
2341 */
Paul Bakker27d66162010-03-17 06:56:01 +00002342 hash_id = ca_crl->sig_alg;
Paul Bakker40ea7de2009-05-03 10:18:48 +00002343
2344 x509_hash( ca_crl->tbs.p, ca_crl->tbs.len, hash_id, hash );
2345
2346 if( !rsa_pkcs1_verify( &trust_ca->rsa, RSA_PUBLIC, hash_id,
2347 0, hash, ca_crl->sig.p ) == 0 )
2348 {
2349 /*
2350 * CRL is not trusted
2351 */
2352 *flags |= BADCRL_NOT_TRUSTED;
2353 break;
2354 }
2355
2356 /*
2357 * Check for validity of CRL (Do not drop out)
2358 */
2359 if( x509parse_time_expired( &ca_crl->next_update ) )
2360 *flags |= BADCRL_EXPIRED;
2361
2362 /*
2363 * Check if certificate is revoked
2364 */
2365 if( x509parse_revoked(crt, ca_crl) )
2366 {
2367 *flags |= BADCERT_REVOKED;
2368 break;
2369 }
2370
2371 ca_crl = ca_crl->next;
2372 }
2373
Paul Bakker5121ce52009-01-03 21:22:43 +00002374 if( *flags != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00002375 return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +00002376
2377 return( 0 );
2378}
2379
2380/*
2381 * Unallocate all certificate data
2382 */
2383void x509_free( x509_cert *crt )
2384{
2385 x509_cert *cert_cur = crt;
2386 x509_cert *cert_prv;
2387 x509_name *name_cur;
2388 x509_name *name_prv;
2389
2390 if( crt == NULL )
2391 return;
2392
2393 do
2394 {
2395 rsa_free( &cert_cur->rsa );
2396
2397 name_cur = cert_cur->issuer.next;
2398 while( name_cur != NULL )
2399 {
2400 name_prv = name_cur;
2401 name_cur = name_cur->next;
2402 memset( name_prv, 0, sizeof( x509_name ) );
2403 free( name_prv );
2404 }
2405
2406 name_cur = cert_cur->subject.next;
2407 while( name_cur != NULL )
2408 {
2409 name_prv = name_cur;
2410 name_cur = name_cur->next;
2411 memset( name_prv, 0, sizeof( x509_name ) );
2412 free( name_prv );
2413 }
2414
2415 if( cert_cur->raw.p != NULL )
2416 {
2417 memset( cert_cur->raw.p, 0, cert_cur->raw.len );
2418 free( cert_cur->raw.p );
2419 }
2420
2421 cert_cur = cert_cur->next;
2422 }
2423 while( cert_cur != NULL );
2424
2425 cert_cur = crt;
2426 do
2427 {
2428 cert_prv = cert_cur;
2429 cert_cur = cert_cur->next;
2430
2431 memset( cert_prv, 0, sizeof( x509_cert ) );
2432 if( cert_prv != crt )
2433 free( cert_prv );
2434 }
2435 while( cert_cur != NULL );
2436}
2437
Paul Bakkerd98030e2009-05-02 15:13:40 +00002438/*
2439 * Unallocate all CRL data
2440 */
2441void x509_crl_free( x509_crl *crl )
2442{
2443 x509_crl *crl_cur = crl;
2444 x509_crl *crl_prv;
2445 x509_name *name_cur;
2446 x509_name *name_prv;
2447 x509_crl_entry *entry_cur;
2448 x509_crl_entry *entry_prv;
2449
2450 if( crl == NULL )
2451 return;
2452
2453 do
2454 {
2455 name_cur = crl_cur->issuer.next;
2456 while( name_cur != NULL )
2457 {
2458 name_prv = name_cur;
2459 name_cur = name_cur->next;
2460 memset( name_prv, 0, sizeof( x509_name ) );
2461 free( name_prv );
2462 }
2463
2464 entry_cur = crl_cur->entry.next;
2465 while( entry_cur != NULL )
2466 {
2467 entry_prv = entry_cur;
2468 entry_cur = entry_cur->next;
2469 memset( entry_prv, 0, sizeof( x509_crl_entry ) );
2470 free( entry_prv );
2471 }
2472
2473 if( crl_cur->raw.p != NULL )
2474 {
2475 memset( crl_cur->raw.p, 0, crl_cur->raw.len );
2476 free( crl_cur->raw.p );
2477 }
2478
2479 crl_cur = crl_cur->next;
2480 }
2481 while( crl_cur != NULL );
2482
2483 crl_cur = crl;
2484 do
2485 {
2486 crl_prv = crl_cur;
2487 crl_cur = crl_cur->next;
2488
2489 memset( crl_prv, 0, sizeof( x509_crl ) );
2490 if( crl_prv != crl )
2491 free( crl_prv );
2492 }
2493 while( crl_cur != NULL );
2494}
2495
Paul Bakker40e46942009-01-03 21:51:57 +00002496#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002497
Paul Bakker40e46942009-01-03 21:51:57 +00002498#include "polarssl/certs.h"
Paul Bakker5121ce52009-01-03 21:22:43 +00002499
2500/*
2501 * Checkup routine
2502 */
2503int x509_self_test( int verbose )
2504{
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002505#if defined(POLARSSL_MD5_C)
Paul Bakker5121ce52009-01-03 21:22:43 +00002506 int ret, i, j;
2507 x509_cert cacert;
2508 x509_cert clicert;
2509 rsa_context rsa;
2510
2511 if( verbose != 0 )
2512 printf( " X.509 certificate load: " );
2513
2514 memset( &clicert, 0, sizeof( x509_cert ) );
2515
2516 ret = x509parse_crt( &clicert, (unsigned char *) test_cli_crt,
2517 strlen( test_cli_crt ) );
2518 if( ret != 0 )
2519 {
2520 if( verbose != 0 )
2521 printf( "failed\n" );
2522
2523 return( ret );
2524 }
2525
2526 memset( &cacert, 0, sizeof( x509_cert ) );
2527
2528 ret = x509parse_crt( &cacert, (unsigned char *) test_ca_crt,
2529 strlen( test_ca_crt ) );
2530 if( ret != 0 )
2531 {
2532 if( verbose != 0 )
2533 printf( "failed\n" );
2534
2535 return( ret );
2536 }
2537
2538 if( verbose != 0 )
2539 printf( "passed\n X.509 private key load: " );
2540
2541 i = strlen( test_ca_key );
2542 j = strlen( test_ca_pwd );
2543
2544 if( ( ret = x509parse_key( &rsa,
2545 (unsigned char *) test_ca_key, i,
2546 (unsigned char *) test_ca_pwd, j ) ) != 0 )
2547 {
2548 if( verbose != 0 )
2549 printf( "failed\n" );
2550
2551 return( ret );
2552 }
2553
2554 if( verbose != 0 )
2555 printf( "passed\n X.509 signature verify: ");
2556
Paul Bakker1973e4c2009-07-10 22:32:40 +00002557 ret = x509parse_verify( &clicert, &cacert, NULL, "PolarSSL Client 2", &i );
Paul Bakker5121ce52009-01-03 21:22:43 +00002558 if( ret != 0 )
2559 {
2560 if( verbose != 0 )
2561 printf( "failed\n" );
2562
2563 return( ret );
2564 }
2565
2566 if( verbose != 0 )
2567 printf( "passed\n\n" );
2568
2569 x509_free( &cacert );
2570 x509_free( &clicert );
2571 rsa_free( &rsa );
2572
2573 return( 0 );
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002574#else
2575 ((void) verbose);
2576 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
2577#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00002578}
2579
2580#endif
2581
2582#endif