blob: 68d4b70302f5d6db225b80497a08467eaf24d637 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * X.509 certificate and private key decoding
3 *
Paul Bakker77b385e2009-07-28 17:23:11 +00004 * Copyright (C) 2006-2009, Paul Bakker <polarssl_maintainer at polarssl.org>
5 * All rights reserved.
Paul Bakkere0ccd0a2009-01-04 16:27:10 +00006 *
Paul Bakker77b385e2009-07-28 17:23:11 +00007 * Joined copyright on original XySSL code with: Christophe Devine
Paul Bakker5121ce52009-01-03 21:22:43 +00008 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23/*
24 * The ITU-T X.509 standard defines a certificat format for PKI.
25 *
26 * http://www.ietf.org/rfc/rfc2459.txt
27 * http://www.ietf.org/rfc/rfc3279.txt
28 *
29 * ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
30 *
31 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
32 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
33 */
34
Paul Bakker40e46942009-01-03 21:51:57 +000035#include "polarssl/config.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000036
Paul Bakker40e46942009-01-03 21:51:57 +000037#if defined(POLARSSL_X509_PARSE_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000038
Paul Bakker40e46942009-01-03 21:51:57 +000039#include "polarssl/x509.h"
40#include "polarssl/base64.h"
41#include "polarssl/des.h"
42#include "polarssl/md2.h"
43#include "polarssl/md4.h"
44#include "polarssl/md5.h"
45#include "polarssl/sha1.h"
Paul Bakker026c03b2009-03-28 17:53:03 +000046#include "polarssl/sha2.h"
47#include "polarssl/sha4.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000048
49#include <string.h>
50#include <stdlib.h>
51#include <stdio.h>
52#include <time.h>
53
54/*
55 * ASN.1 DER decoding routines
56 */
57static int asn1_get_len( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +000058 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +000059 int *len )
60{
61 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +000062 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000063
64 if( ( **p & 0x80 ) == 0 )
65 *len = *(*p)++;
66 else
67 {
68 switch( **p & 0x7F )
69 {
70 case 1:
71 if( ( end - *p ) < 2 )
Paul Bakker40e46942009-01-03 21:51:57 +000072 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000073
74 *len = (*p)[1];
75 (*p) += 2;
76 break;
77
78 case 2:
79 if( ( end - *p ) < 3 )
Paul Bakker40e46942009-01-03 21:51:57 +000080 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000081
82 *len = ( (*p)[1] << 8 ) | (*p)[2];
83 (*p) += 3;
84 break;
85
86 default:
Paul Bakker40e46942009-01-03 21:51:57 +000087 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
Paul Bakker5121ce52009-01-03 21:22:43 +000088 break;
89 }
90 }
91
92 if( *len > (int) ( end - *p ) )
Paul Bakker40e46942009-01-03 21:51:57 +000093 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000094
95 return( 0 );
96}
97
98static int asn1_get_tag( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +000099 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000100 int *len, int tag )
101{
102 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000103 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000104
105 if( **p != tag )
Paul Bakker40e46942009-01-03 21:51:57 +0000106 return( POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000107
108 (*p)++;
109
110 return( asn1_get_len( p, end, len ) );
111}
112
113static int asn1_get_bool( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000114 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000115 int *val )
116{
117 int ret, len;
118
119 if( ( ret = asn1_get_tag( p, end, &len, ASN1_BOOLEAN ) ) != 0 )
120 return( ret );
121
122 if( len != 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000123 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000124
125 *val = ( **p != 0 ) ? 1 : 0;
126 (*p)++;
127
128 return( 0 );
129}
130
131static int asn1_get_int( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000132 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000133 int *val )
134{
135 int ret, len;
136
137 if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
138 return( ret );
139
140 if( len > (int) sizeof( int ) || ( **p & 0x80 ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000141 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000142
143 *val = 0;
144
145 while( len-- > 0 )
146 {
147 *val = ( *val << 8 ) | **p;
148 (*p)++;
149 }
150
151 return( 0 );
152}
153
154static int asn1_get_mpi( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000155 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000156 mpi *X )
157{
158 int ret, len;
159
160 if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
161 return( ret );
162
163 ret = mpi_read_binary( X, *p, len );
164
165 *p += len;
166
167 return( ret );
168}
169
170/*
171 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
172 */
173static int x509_get_version( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000174 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000175 int *ver )
176{
177 int ret, len;
178
179 if( ( ret = asn1_get_tag( p, end, &len,
180 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) != 0 )
181 {
Paul Bakker40e46942009-01-03 21:51:57 +0000182 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker5121ce52009-01-03 21:22:43 +0000183 return( *ver = 0 );
184
185 return( ret );
186 }
187
188 end = *p + len;
189
190 if( ( ret = asn1_get_int( p, end, ver ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000191 return( POLARSSL_ERR_X509_CERT_INVALID_VERSION | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000192
193 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000194 return( POLARSSL_ERR_X509_CERT_INVALID_VERSION |
195 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000196
197 return( 0 );
198}
199
200/*
201 * CertificateSerialNumber ::= INTEGER
202 */
203static int x509_get_serial( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000204 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000205 x509_buf *serial )
206{
207 int ret;
208
209 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000210 return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL |
211 POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000212
213 if( **p != ( ASN1_CONTEXT_SPECIFIC | ASN1_PRIMITIVE | 2 ) &&
214 **p != ASN1_INTEGER )
Paul Bakker40e46942009-01-03 21:51:57 +0000215 return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL |
216 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000217
218 serial->tag = *(*p)++;
219
220 if( ( ret = asn1_get_len( p, end, &serial->len ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000221 return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000222
223 serial->p = *p;
224 *p += serial->len;
225
226 return( 0 );
227}
228
229/*
230 * AlgorithmIdentifier ::= SEQUENCE {
231 * algorithm OBJECT IDENTIFIER,
232 * parameters ANY DEFINED BY algorithm OPTIONAL }
233 */
234static int x509_get_alg( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000235 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000236 x509_buf *alg )
237{
238 int ret, len;
239
240 if( ( ret = asn1_get_tag( p, end, &len,
241 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000242 return( POLARSSL_ERR_X509_CERT_INVALID_ALG | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000243
244 end = *p + len;
245 alg->tag = **p;
246
247 if( ( ret = asn1_get_tag( p, end, &alg->len, ASN1_OID ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000248 return( POLARSSL_ERR_X509_CERT_INVALID_ALG | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000249
250 alg->p = *p;
251 *p += alg->len;
252
253 if( *p == end )
254 return( 0 );
255
256 /*
257 * assume the algorithm parameters must be NULL
258 */
259 if( ( ret = asn1_get_tag( p, end, &len, ASN1_NULL ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000260 return( POLARSSL_ERR_X509_CERT_INVALID_ALG | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000261
262 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000263 return( POLARSSL_ERR_X509_CERT_INVALID_ALG |
264 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000265
266 return( 0 );
267}
268
269/*
270 * RelativeDistinguishedName ::=
271 * SET OF AttributeTypeAndValue
272 *
273 * AttributeTypeAndValue ::= SEQUENCE {
274 * type AttributeType,
275 * value AttributeValue }
276 *
277 * AttributeType ::= OBJECT IDENTIFIER
278 *
279 * AttributeValue ::= ANY DEFINED BY AttributeType
280 */
281static int x509_get_name( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000282 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000283 x509_name *cur )
284{
285 int ret, len;
Paul Bakkerff60ee62010-03-16 21:09:09 +0000286 const unsigned char *end2;
Paul Bakker5121ce52009-01-03 21:22:43 +0000287 x509_buf *oid;
288 x509_buf *val;
289
290 if( ( ret = asn1_get_tag( p, end, &len,
291 ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000292 return( POLARSSL_ERR_X509_CERT_INVALID_NAME | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000293
294 end2 = end;
295 end = *p + len;
296
297 if( ( ret = asn1_get_tag( p, end, &len,
298 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000299 return( POLARSSL_ERR_X509_CERT_INVALID_NAME | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000300
301 if( *p + len != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000302 return( POLARSSL_ERR_X509_CERT_INVALID_NAME |
303 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000304
305 oid = &cur->oid;
306 oid->tag = **p;
307
308 if( ( ret = asn1_get_tag( p, end, &oid->len, ASN1_OID ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000309 return( POLARSSL_ERR_X509_CERT_INVALID_NAME | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000310
311 oid->p = *p;
312 *p += oid->len;
313
314 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000315 return( POLARSSL_ERR_X509_CERT_INVALID_NAME |
316 POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000317
318 if( **p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING &&
319 **p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING &&
320 **p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING )
Paul Bakker40e46942009-01-03 21:51:57 +0000321 return( POLARSSL_ERR_X509_CERT_INVALID_NAME |
322 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000323
324 val = &cur->val;
325 val->tag = *(*p)++;
326
327 if( ( ret = asn1_get_len( p, end, &val->len ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000328 return( POLARSSL_ERR_X509_CERT_INVALID_NAME | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000329
330 val->p = *p;
331 *p += val->len;
332
333 cur->next = NULL;
334
335 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000336 return( POLARSSL_ERR_X509_CERT_INVALID_NAME |
337 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000338
339 /*
340 * recurse until end of SEQUENCE is reached
341 */
342 if( *p == end2 )
343 return( 0 );
344
345 cur->next = (x509_name *) malloc(
346 sizeof( x509_name ) );
347
348 if( cur->next == NULL )
349 return( 1 );
350
351 return( x509_get_name( p, end2, cur->next ) );
352}
353
354/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000355 * Time ::= CHOICE {
356 * utcTime UTCTime,
357 * generalTime GeneralizedTime }
358 */
Paul Bakker91200182010-02-18 21:26:15 +0000359static int x509_get_time( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000360 const unsigned char *end,
Paul Bakkerd98030e2009-05-02 15:13:40 +0000361 x509_time *time )
362{
363 int ret, len;
364 char date[64];
Paul Bakker91200182010-02-18 21:26:15 +0000365 unsigned char tag;
Paul Bakkerd98030e2009-05-02 15:13:40 +0000366
Paul Bakker91200182010-02-18 21:26:15 +0000367 if( ( end - *p ) < 1 )
368 return( POLARSSL_ERR_X509_CERT_INVALID_DATE | POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakkerd98030e2009-05-02 15:13:40 +0000369
Paul Bakker91200182010-02-18 21:26:15 +0000370 tag = **p;
Paul Bakkerd98030e2009-05-02 15:13:40 +0000371
Paul Bakker91200182010-02-18 21:26:15 +0000372 if ( tag == ASN1_UTC_TIME )
373 {
374 (*p)++;
375 ret = asn1_get_len( p, end, &len );
376
377 if( ret != 0 )
378 return( POLARSSL_ERR_X509_CERT_INVALID_DATE | ret );
Paul Bakkerd98030e2009-05-02 15:13:40 +0000379
Paul Bakker91200182010-02-18 21:26:15 +0000380 memset( date, 0, sizeof( date ) );
381 memcpy( date, *p, ( len < (int) sizeof( date ) - 1 ) ?
382 len : (int) sizeof( date ) - 1 );
Paul Bakkerd98030e2009-05-02 15:13:40 +0000383
Paul Bakker91200182010-02-18 21:26:15 +0000384 if( sscanf( date, "%2d%2d%2d%2d%2d%2d",
385 &time->year, &time->mon, &time->day,
386 &time->hour, &time->min, &time->sec ) < 5 )
387 return( POLARSSL_ERR_X509_CERT_INVALID_DATE );
Paul Bakkerd98030e2009-05-02 15:13:40 +0000388
Paul Bakker91200182010-02-18 21:26:15 +0000389 time->year += 100 * ( time->year < 90 );
390 time->year += 1900;
391
392 *p += len;
393
394 return( 0 );
395 }
396 else if ( tag == ASN1_GENERALIZED_TIME )
397 {
398 (*p)++;
399 ret = asn1_get_len( p, end, &len );
400
401 if( ret != 0 )
402 return( POLARSSL_ERR_X509_CERT_INVALID_DATE | ret );
403
404 memset( date, 0, sizeof( date ) );
405 memcpy( date, *p, ( len < (int) sizeof( date ) - 1 ) ?
406 len : (int) sizeof( date ) - 1 );
407
408 if( sscanf( date, "%4d%2d%2d%2d%2d%2d",
409 &time->year, &time->mon, &time->day,
410 &time->hour, &time->min, &time->sec ) < 5 )
411 return( POLARSSL_ERR_X509_CERT_INVALID_DATE );
412
413 *p += len;
414
415 return( 0 );
416 }
417 else
418 return( POLARSSL_ERR_X509_CERT_INVALID_DATE | POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakkerd98030e2009-05-02 15:13:40 +0000419}
420
421
422/*
423 * Validity ::= SEQUENCE {
424 * notBefore Time,
425 * notAfter Time }
426 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000427static int x509_get_dates( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000428 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000429 x509_time *from,
430 x509_time *to )
431{
432 int ret, len;
Paul Bakker5121ce52009-01-03 21:22:43 +0000433
434 if( ( ret = asn1_get_tag( p, end, &len,
435 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000436 return( POLARSSL_ERR_X509_CERT_INVALID_DATE | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000437
438 end = *p + len;
439
Paul Bakker91200182010-02-18 21:26:15 +0000440 if( ( ret = x509_get_time( p, end, from ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +0000441 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000442
Paul Bakker91200182010-02-18 21:26:15 +0000443 if( ( ret = x509_get_time( p, end, to ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +0000444 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000445
446 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000447 return( POLARSSL_ERR_X509_CERT_INVALID_DATE |
448 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000449
450 return( 0 );
451}
452
453/*
454 * SubjectPublicKeyInfo ::= SEQUENCE {
455 * algorithm AlgorithmIdentifier,
456 * subjectPublicKey BIT STRING }
457 */
458static int x509_get_pubkey( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000459 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000460 x509_buf *pk_alg_oid,
461 mpi *N, mpi *E )
462{
463 int ret, len;
464 unsigned char *end2;
465
466 if( ( ret = x509_get_alg( p, end, pk_alg_oid ) ) != 0 )
467 return( ret );
468
469 /*
470 * only RSA public keys handled at this time
471 */
472 if( pk_alg_oid->len != 9 ||
473 memcmp( pk_alg_oid->p, OID_PKCS1_RSA, 9 ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000474 return( POLARSSL_ERR_X509_CERT_UNKNOWN_PK_ALG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000475
476 if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000477 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000478
479 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000480 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY |
481 POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000482
483 end2 = *p + len;
484
485 if( *(*p)++ != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000486 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY );
Paul Bakker5121ce52009-01-03 21:22:43 +0000487
488 /*
489 * RSAPublicKey ::= SEQUENCE {
490 * modulus INTEGER, -- n
491 * publicExponent INTEGER -- e
492 * }
493 */
494 if( ( ret = asn1_get_tag( p, end2, &len,
495 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000496 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000497
498 if( *p + len != end2 )
Paul Bakker40e46942009-01-03 21:51:57 +0000499 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY |
500 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000501
502 if( ( ret = asn1_get_mpi( p, end2, N ) ) != 0 ||
503 ( ret = asn1_get_mpi( p, end2, E ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000504 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000505
506 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000507 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY |
508 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000509
510 return( 0 );
511}
512
513static int x509_get_sig( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000514 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000515 x509_buf *sig )
516{
517 int ret, len;
518
519 sig->tag = **p;
520
521 if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000522 return( POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000523
524 if( --len < 1 || *(*p)++ != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000525 return( POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000526
527 sig->len = len;
528 sig->p = *p;
529
530 *p += len;
531
532 return( 0 );
533}
534
535/*
536 * X.509 v2/v3 unique identifier (not parsed)
537 */
538static int x509_get_uid( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000539 const unsigned char *end,
Paul Bakker5121ce52009-01-03 21:22:43 +0000540 x509_buf *uid, int n )
541{
542 int ret;
543
544 if( *p == end )
545 return( 0 );
546
547 uid->tag = **p;
548
549 if( ( ret = asn1_get_tag( p, end, &uid->len,
550 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | n ) ) != 0 )
551 {
Paul Bakker40e46942009-01-03 21:51:57 +0000552 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker5121ce52009-01-03 21:22:43 +0000553 return( 0 );
554
555 return( ret );
556 }
557
558 uid->p = *p;
559 *p += uid->len;
560
561 return( 0 );
562}
563
564/*
Paul Bakkerd98030e2009-05-02 15:13:40 +0000565 * X.509 Extensions (No parsing of extensions, pointer should
566 * be either manually updated or extensions should be parsed!
Paul Bakker5121ce52009-01-03 21:22:43 +0000567 */
568static int x509_get_ext( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000569 const unsigned char *end,
Paul Bakkerd98030e2009-05-02 15:13:40 +0000570 x509_buf *ext )
Paul Bakker5121ce52009-01-03 21:22:43 +0000571{
572 int ret, len;
Paul Bakker5121ce52009-01-03 21:22:43 +0000573
574 if( *p == end )
575 return( 0 );
576
577 ext->tag = **p;
Paul Bakkerff60ee62010-03-16 21:09:09 +0000578
Paul Bakker5121ce52009-01-03 21:22:43 +0000579 if( ( ret = asn1_get_tag( p, end, &ext->len,
580 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000581 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000582
583 ext->p = *p;
584 end = *p + ext->len;
585
586 /*
587 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
588 *
589 * Extension ::= SEQUENCE {
590 * extnID OBJECT IDENTIFIER,
591 * critical BOOLEAN DEFAULT FALSE,
592 * extnValue OCTET STRING }
593 */
594 if( ( ret = asn1_get_tag( p, end, &len,
595 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000596 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000597
598 if( end != *p + len )
Paul Bakker40e46942009-01-03 21:51:57 +0000599 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
600 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000601
Paul Bakkerd98030e2009-05-02 15:13:40 +0000602 return( 0 );
603}
604
605/*
606 * X.509 CRL v2 extensions (no extensions parsed yet.)
607 */
608static int x509_get_crl_ext( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000609 const unsigned char *end,
610 x509_buf *ext )
Paul Bakkerd98030e2009-05-02 15:13:40 +0000611{
612 int ret, len;
613
614 if( ( ret = x509_get_ext( p, end, ext ) ) != 0 )
615 {
616 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
617 return( 0 );
618
619 return( ret );
620 }
621
622 while( *p < end )
623 {
624 if( ( ret = asn1_get_tag( p, end, &len,
625 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
626 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
627
628 *p += len;
629 }
630
631 if( *p != end )
632 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
633 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
634
635 return( 0 );
636}
637
638/*
639 * X.509 v3 extensions (only BasicConstraints are parsed)
640 */
641static int x509_get_crt_ext( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000642 const unsigned char *end,
643 x509_buf *ext,
644 int *ca_istrue,
645 int *max_pathlen )
Paul Bakkerd98030e2009-05-02 15:13:40 +0000646{
647 int ret, len;
648 int is_critical = 1;
649 int is_cacert = 0;
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000650 unsigned char *end_ext_data, *end_ext_octet;
Paul Bakkerd98030e2009-05-02 15:13:40 +0000651
652 if( ( ret = x509_get_ext( p, end, ext ) ) != 0 )
653 {
654 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
655 return( 0 );
656
657 return( ret );
658 }
659
Paul Bakker5121ce52009-01-03 21:22:43 +0000660 while( *p < end )
661 {
662 if( ( ret = asn1_get_tag( p, end, &len,
663 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000664 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000665
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000666 end_ext_data = *p + len;
667
Paul Bakker5121ce52009-01-03 21:22:43 +0000668 if( memcmp( *p, "\x06\x03\x55\x1D\x13", 5 ) != 0 )
669 {
670 *p += len;
671 continue;
672 }
673
674 *p += 5;
675
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000676 if( ( ret = asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 &&
Paul Bakker40e46942009-01-03 21:51:57 +0000677 ( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) )
678 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000679
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000680 if( ( ret = asn1_get_tag( p, end_ext_data, &len,
Paul Bakker5121ce52009-01-03 21:22:43 +0000681 ASN1_OCTET_STRING ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000682 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000683
684 /*
685 * BasicConstraints ::= SEQUENCE {
686 * cA BOOLEAN DEFAULT FALSE,
687 * pathLenConstraint INTEGER (0..MAX) OPTIONAL }
688 */
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000689 end_ext_octet = *p + len;
Paul Bakkerff60ee62010-03-16 21:09:09 +0000690
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000691 if( end_ext_octet != end_ext_data )
692 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
693 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000694
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000695 if( ( ret = asn1_get_tag( p, end_ext_octet, &len,
Paul Bakker5121ce52009-01-03 21:22:43 +0000696 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000697 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000698
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000699 if( *p == end_ext_octet )
Paul Bakker5121ce52009-01-03 21:22:43 +0000700 continue;
701
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000702 if( ( ret = asn1_get_bool( p, end_ext_octet, &is_cacert ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000703 {
Paul Bakker40e46942009-01-03 21:51:57 +0000704 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000705 ret = asn1_get_int( p, end_ext_octet, &is_cacert );
Paul Bakker5121ce52009-01-03 21:22:43 +0000706
707 if( ret != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000708 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000709
710 if( is_cacert != 0 )
711 is_cacert = 1;
712 }
713
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000714 if( *p == end_ext_octet )
Paul Bakker5121ce52009-01-03 21:22:43 +0000715 continue;
716
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000717 if( ( ret = asn1_get_int( p, end_ext_octet, max_pathlen ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000718 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000719
Paul Bakkerc6ce8382009-07-27 21:34:45 +0000720 if( *p != end_ext_octet )
Paul Bakker40e46942009-01-03 21:51:57 +0000721 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
722 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000723
724 max_pathlen++;
725 }
726
727 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000728 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
729 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000730
731 *ca_istrue = is_critical & is_cacert;
732
733 return( 0 );
734}
735
736/*
Paul Bakkerd98030e2009-05-02 15:13:40 +0000737 * X.509 CRL Entries
738 */
739static int x509_get_entries( unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000740 const unsigned char *end,
Paul Bakkerd98030e2009-05-02 15:13:40 +0000741 x509_crl_entry *entry )
742{
Paul Bakker9be19372009-07-27 20:21:53 +0000743 int ret, entry_len;
Paul Bakkerd98030e2009-05-02 15:13:40 +0000744 x509_crl_entry *cur_entry = entry;
745
746 if( *p == end )
747 return( 0 );
748
Paul Bakker9be19372009-07-27 20:21:53 +0000749 if( ( ret = asn1_get_tag( p, end, &entry_len,
Paul Bakkerd98030e2009-05-02 15:13:40 +0000750 ASN1_SEQUENCE | ASN1_CONSTRUCTED ) ) != 0 )
751 {
752 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
753 return( 0 );
754
755 return( ret );
756 }
757
Paul Bakker9be19372009-07-27 20:21:53 +0000758 end = *p + entry_len;
Paul Bakkerd98030e2009-05-02 15:13:40 +0000759
760 while( *p < end )
761 {
762 int len2;
763
764 if( ( ret = asn1_get_tag( p, end, &len2,
765 ASN1_SEQUENCE | ASN1_CONSTRUCTED ) ) != 0 )
766 {
Paul Bakkerd98030e2009-05-02 15:13:40 +0000767 return( ret );
768 }
769
Paul Bakker9be19372009-07-27 20:21:53 +0000770 cur_entry->raw.tag = **p;
771 cur_entry->raw.p = *p;
772 cur_entry->raw.len = len2;
773
Paul Bakkerd98030e2009-05-02 15:13:40 +0000774 if( ( ret = x509_get_serial( p, end, &cur_entry->serial ) ) != 0 )
775 return( ret );
776
Paul Bakker91200182010-02-18 21:26:15 +0000777 if( ( ret = x509_get_time( p, end, &cur_entry->revocation_date ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +0000778 return( ret );
779
780 if( ( ret = x509_get_crl_ext( p, end, &cur_entry->entry_ext ) ) != 0 )
781 return( ret );
782
783 if ( *p < end ) {
784 cur_entry->next = malloc( sizeof( x509_crl_entry ) );
785 cur_entry = cur_entry->next;
786 memset( cur_entry, 0, sizeof( x509_crl_entry ) );
787 }
788 }
789
790 return( 0 );
791}
792
793/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000794 * Parse one or more certificates and add them to the chained list
795 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000796int x509parse_crt( x509_cert *chain, const unsigned char *buf, int buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000797{
798 int ret, len;
Paul Bakkerff60ee62010-03-16 21:09:09 +0000799 const unsigned char *s1, *s2;
Paul Bakker5121ce52009-01-03 21:22:43 +0000800 unsigned char *p, *end;
801 x509_cert *crt;
802
803 crt = chain;
804
Paul Bakker320a4b52009-03-28 18:52:39 +0000805 /*
806 * Check for valid input
807 */
808 if( crt == NULL || buf == NULL )
809 return( 1 );
810
Paul Bakkere9581d62009-03-28 20:29:25 +0000811 while( crt->version != 0 && crt->next != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000812 crt = crt->next;
813
814 /*
Paul Bakker320a4b52009-03-28 18:52:39 +0000815 * Add new certificate on the end of the chain if needed.
816 */
Paul Bakkere9581d62009-03-28 20:29:25 +0000817 if ( crt->version != 0 && crt->next == NULL)
Paul Bakker320a4b52009-03-28 18:52:39 +0000818 {
819 crt->next = (x509_cert *) malloc( sizeof( x509_cert ) );
820
Paul Bakker7d06ad22009-05-02 15:53:56 +0000821 if( crt->next == NULL )
822 {
Paul Bakker320a4b52009-03-28 18:52:39 +0000823 x509_free( crt );
Paul Bakker7d06ad22009-05-02 15:53:56 +0000824 return( 1 );
825 }
Paul Bakker320a4b52009-03-28 18:52:39 +0000826
Paul Bakker7d06ad22009-05-02 15:53:56 +0000827 crt = crt->next;
828 memset( crt, 0, sizeof( x509_cert ) );
Paul Bakker320a4b52009-03-28 18:52:39 +0000829 }
830
831 /*
Paul Bakker5121ce52009-01-03 21:22:43 +0000832 * check if the certificate is encoded in base64
833 */
834 s1 = (unsigned char *) strstr( (char *) buf,
835 "-----BEGIN CERTIFICATE-----" );
836
837 if( s1 != NULL )
838 {
839 s2 = (unsigned char *) strstr( (char *) buf,
840 "-----END CERTIFICATE-----" );
841
842 if( s2 == NULL || s2 <= s1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000843 return( POLARSSL_ERR_X509_CERT_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +0000844
845 s1 += 27;
846 if( *s1 == '\r' ) s1++;
847 if( *s1 == '\n' ) s1++;
Paul Bakker40e46942009-01-03 21:51:57 +0000848 else return( POLARSSL_ERR_X509_CERT_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +0000849
850 /*
851 * get the DER data length and decode the buffer
852 */
853 len = 0;
854 ret = base64_decode( NULL, &len, s1, s2 - s1 );
855
Paul Bakker40e46942009-01-03 21:51:57 +0000856 if( ret == POLARSSL_ERR_BASE64_INVALID_CHARACTER )
857 return( POLARSSL_ERR_X509_CERT_INVALID_PEM | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000858
859 if( ( p = (unsigned char *) malloc( len ) ) == NULL )
860 return( 1 );
861
862 if( ( ret = base64_decode( p, &len, s1, s2 - s1 ) ) != 0 )
863 {
864 free( p );
Paul Bakker40e46942009-01-03 21:51:57 +0000865 return( POLARSSL_ERR_X509_CERT_INVALID_PEM | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000866 }
867
868 /*
869 * update the buffer size and offset
870 */
871 s2 += 25;
872 if( *s2 == '\r' ) s2++;
873 if( *s2 == '\n' ) s2++;
874 else
875 {
876 free( p );
Paul Bakker40e46942009-01-03 21:51:57 +0000877 return( POLARSSL_ERR_X509_CERT_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +0000878 }
879
880 buflen -= s2 - buf;
881 buf = s2;
882 }
883 else
884 {
885 /*
886 * nope, copy the raw DER data
887 */
888 p = (unsigned char *) malloc( len = buflen );
889
890 if( p == NULL )
891 return( 1 );
892
893 memcpy( p, buf, buflen );
894
895 buflen = 0;
896 }
897
898 crt->raw.p = p;
899 crt->raw.len = len;
900 end = p + len;
901
902 /*
903 * Certificate ::= SEQUENCE {
904 * tbsCertificate TBSCertificate,
905 * signatureAlgorithm AlgorithmIdentifier,
906 * signatureValue BIT STRING }
907 */
908 if( ( ret = asn1_get_tag( &p, end, &len,
909 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
910 {
Paul Bakker7d06ad22009-05-02 15:53:56 +0000911 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000912 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT );
Paul Bakker5121ce52009-01-03 21:22:43 +0000913 }
914
915 if( len != (int) ( end - p ) )
916 {
Paul Bakker7d06ad22009-05-02 15:53:56 +0000917 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000918 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT |
919 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000920 }
921
922 /*
923 * TBSCertificate ::= SEQUENCE {
924 */
925 crt->tbs.p = p;
926
927 if( ( ret = asn1_get_tag( &p, end, &len,
928 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
929 {
Paul Bakker7d06ad22009-05-02 15:53:56 +0000930 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000931 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000932 }
933
934 end = p + len;
935 crt->tbs.len = end - crt->tbs.p;
936
937 /*
938 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
939 *
940 * CertificateSerialNumber ::= INTEGER
941 *
942 * signature AlgorithmIdentifier
943 */
944 if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 ||
945 ( ret = x509_get_serial( &p, end, &crt->serial ) ) != 0 ||
946 ( ret = x509_get_alg( &p, end, &crt->sig_oid1 ) ) != 0 )
947 {
Paul Bakker7d06ad22009-05-02 15:53:56 +0000948 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +0000949 return( ret );
950 }
951
952 crt->version++;
953
954 if( crt->version > 3 )
955 {
Paul Bakker7d06ad22009-05-02 15:53:56 +0000956 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000957 return( POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION );
Paul Bakker5121ce52009-01-03 21:22:43 +0000958 }
959
960 if( crt->sig_oid1.len != 9 ||
961 memcmp( crt->sig_oid1.p, OID_PKCS1, 8 ) != 0 )
962 {
Paul Bakker7d06ad22009-05-02 15:53:56 +0000963 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000964 return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000965 }
966
967 if( crt->sig_oid1.p[8] < 2 ||
Paul Bakker4593aea2009-02-09 22:32:35 +0000968 ( crt->sig_oid1.p[8] > 5 && crt->sig_oid1.p[8] < 11 ) ||
Paul Bakker7d06ad22009-05-02 15:53:56 +0000969 crt->sig_oid1.p[8] > 14 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000970 {
Paul Bakker7d06ad22009-05-02 15:53:56 +0000971 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000972 return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000973 }
974
975 /*
976 * issuer Name
977 */
978 crt->issuer_raw.p = p;
979
980 if( ( ret = asn1_get_tag( &p, end, &len,
981 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
982 {
Paul Bakker7d06ad22009-05-02 15:53:56 +0000983 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000984 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000985 }
986
987 if( ( ret = x509_get_name( &p, p + len, &crt->issuer ) ) != 0 )
988 {
Paul Bakker7d06ad22009-05-02 15:53:56 +0000989 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +0000990 return( ret );
991 }
992
993 crt->issuer_raw.len = p - crt->issuer_raw.p;
994
995 /*
996 * Validity ::= SEQUENCE {
997 * notBefore Time,
998 * notAfter Time }
999 *
1000 */
1001 if( ( ret = x509_get_dates( &p, end, &crt->valid_from,
1002 &crt->valid_to ) ) != 0 )
1003 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001004 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001005 return( ret );
1006 }
1007
1008 /*
1009 * subject Name
1010 */
1011 crt->subject_raw.p = p;
1012
1013 if( ( ret = asn1_get_tag( &p, end, &len,
1014 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1015 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001016 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +00001017 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001018 }
1019
1020 if( ( ret = x509_get_name( &p, p + len, &crt->subject ) ) != 0 )
1021 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001022 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001023 return( ret );
1024 }
1025
1026 crt->subject_raw.len = p - crt->subject_raw.p;
1027
1028 /*
1029 * SubjectPublicKeyInfo ::= SEQUENCE
1030 * algorithm AlgorithmIdentifier,
1031 * subjectPublicKey BIT STRING }
1032 */
1033 if( ( ret = asn1_get_tag( &p, end, &len,
1034 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1035 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001036 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +00001037 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001038 }
1039
1040 if( ( ret = x509_get_pubkey( &p, p + len, &crt->pk_oid,
1041 &crt->rsa.N, &crt->rsa.E ) ) != 0 )
1042 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001043 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001044 return( ret );
1045 }
1046
1047 if( ( ret = rsa_check_pubkey( &crt->rsa ) ) != 0 )
1048 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001049 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001050 return( ret );
1051 }
1052
1053 crt->rsa.len = mpi_size( &crt->rsa.N );
1054
1055 /*
1056 * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
1057 * -- If present, version shall be v2 or v3
1058 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
1059 * -- If present, version shall be v2 or v3
1060 * extensions [3] EXPLICIT Extensions OPTIONAL
1061 * -- If present, version shall be v3
1062 */
1063 if( crt->version == 2 || crt->version == 3 )
1064 {
1065 ret = x509_get_uid( &p, end, &crt->issuer_id, 1 );
1066 if( ret != 0 )
1067 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001068 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001069 return( ret );
1070 }
1071 }
1072
1073 if( crt->version == 2 || crt->version == 3 )
1074 {
1075 ret = x509_get_uid( &p, end, &crt->subject_id, 2 );
1076 if( ret != 0 )
1077 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001078 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001079 return( ret );
1080 }
1081 }
1082
1083 if( crt->version == 3 )
1084 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00001085 ret = x509_get_crt_ext( &p, end, &crt->v3_ext,
Paul Bakker5121ce52009-01-03 21:22:43 +00001086 &crt->ca_istrue, &crt->max_pathlen );
1087 if( ret != 0 )
1088 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001089 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001090 return( ret );
1091 }
1092 }
1093
1094 if( p != end )
1095 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001096 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +00001097 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT |
1098 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001099 }
1100
1101 end = crt->raw.p + crt->raw.len;
1102
1103 /*
1104 * signatureAlgorithm AlgorithmIdentifier,
1105 * signatureValue BIT STRING
1106 */
1107 if( ( ret = x509_get_alg( &p, end, &crt->sig_oid2 ) ) != 0 )
1108 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001109 x509_free( crt );
Paul Bakker5121ce52009-01-03 21:22:43 +00001110 return( ret );
1111 }
1112
Paul Bakker320a4b52009-03-28 18:52:39 +00001113 if( memcmp( crt->sig_oid1.p, crt->sig_oid2.p, crt->sig_oid1.len ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001114 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001115 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +00001116 return( POLARSSL_ERR_X509_CERT_SIG_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001117 }
1118
1119 if( ( ret = x509_get_sig( &p, end, &crt->sig ) ) != 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
1125 if( p != end )
1126 {
Paul Bakker7d06ad22009-05-02 15:53:56 +00001127 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +00001128 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT |
1129 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001130 }
1131
Paul Bakker5121ce52009-01-03 21:22:43 +00001132 if( buflen > 0 )
Paul Bakker320a4b52009-03-28 18:52:39 +00001133 {
1134 crt->next = (x509_cert *) malloc( sizeof( x509_cert ) );
1135
Paul Bakker7d06ad22009-05-02 15:53:56 +00001136 if( crt->next == NULL )
1137 {
Paul Bakker320a4b52009-03-28 18:52:39 +00001138 x509_free( crt );
Paul Bakker7d06ad22009-05-02 15:53:56 +00001139 return( 1 );
1140 }
Paul Bakker320a4b52009-03-28 18:52:39 +00001141
Paul Bakker7d06ad22009-05-02 15:53:56 +00001142 crt = crt->next;
1143 memset( crt, 0, sizeof( x509_cert ) );
Paul Bakker320a4b52009-03-28 18:52:39 +00001144
Paul Bakker5121ce52009-01-03 21:22:43 +00001145 return( x509parse_crt( crt, buf, buflen ) );
Paul Bakker320a4b52009-03-28 18:52:39 +00001146 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001147
1148 return( 0 );
1149}
1150
1151/*
Paul Bakkerd98030e2009-05-02 15:13:40 +00001152 * Parse one or more CRLs and add them to the chained list
1153 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001154int x509parse_crl( x509_crl *chain, const unsigned char *buf, int buflen )
Paul Bakkerd98030e2009-05-02 15:13:40 +00001155{
1156 int ret, len;
1157 unsigned char *s1, *s2;
1158 unsigned char *p, *end;
1159 x509_crl *crl;
1160
1161 crl = chain;
1162
1163 /*
1164 * Check for valid input
1165 */
1166 if( crl == NULL || buf == NULL )
1167 return( 1 );
1168
1169 while( crl->version != 0 && crl->next != NULL )
1170 crl = crl->next;
1171
1172 /*
1173 * Add new CRL on the end of the chain if needed.
1174 */
1175 if ( crl->version != 0 && crl->next == NULL)
1176 {
1177 crl->next = (x509_crl *) malloc( sizeof( x509_crl ) );
1178
Paul Bakker7d06ad22009-05-02 15:53:56 +00001179 if( crl->next == NULL )
1180 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00001181 x509_crl_free( crl );
Paul Bakker7d06ad22009-05-02 15:53:56 +00001182 return( 1 );
1183 }
Paul Bakkerd98030e2009-05-02 15:13:40 +00001184
Paul Bakker7d06ad22009-05-02 15:53:56 +00001185 crl = crl->next;
1186 memset( crl, 0, sizeof( x509_crl ) );
Paul Bakkerd98030e2009-05-02 15:13:40 +00001187 }
1188
1189 /*
1190 * check if the CRL is encoded in base64
1191 */
1192 s1 = (unsigned char *) strstr( (char *) buf,
1193 "-----BEGIN X509 CRL-----" );
1194
1195 if( s1 != NULL )
1196 {
1197 s2 = (unsigned char *) strstr( (char *) buf,
1198 "-----END X509 CRL-----" );
1199
1200 if( s2 == NULL || s2 <= s1 )
1201 return( POLARSSL_ERR_X509_CERT_INVALID_PEM );
1202
1203 s1 += 24;
1204 if( *s1 == '\r' ) s1++;
1205 if( *s1 == '\n' ) s1++;
1206 else return( POLARSSL_ERR_X509_CERT_INVALID_PEM );
1207
1208 /*
1209 * get the DER data length and decode the buffer
1210 */
1211 len = 0;
1212 ret = base64_decode( NULL, &len, s1, s2 - s1 );
1213
1214 if( ret == POLARSSL_ERR_BASE64_INVALID_CHARACTER )
1215 return( POLARSSL_ERR_X509_CERT_INVALID_PEM | ret );
1216
1217 if( ( p = (unsigned char *) malloc( len ) ) == NULL )
1218 return( 1 );
1219
1220 if( ( ret = base64_decode( p, &len, s1, s2 - s1 ) ) != 0 )
1221 {
1222 free( p );
1223 return( POLARSSL_ERR_X509_CERT_INVALID_PEM | ret );
1224 }
1225
1226 /*
1227 * update the buffer size and offset
1228 */
1229 s2 += 22;
1230 if( *s2 == '\r' ) s2++;
1231 if( *s2 == '\n' ) s2++;
1232 else
1233 {
1234 free( p );
1235 return( POLARSSL_ERR_X509_CERT_INVALID_PEM );
1236 }
1237
1238 buflen -= s2 - buf;
1239 buf = s2;
1240 }
1241 else
1242 {
1243 /*
1244 * nope, copy the raw DER data
1245 */
1246 p = (unsigned char *) malloc( len = buflen );
1247
1248 if( p == NULL )
1249 return( 1 );
1250
1251 memcpy( p, buf, buflen );
1252
1253 buflen = 0;
1254 }
1255
1256 crl->raw.p = p;
1257 crl->raw.len = len;
1258 end = p + len;
1259
1260 /*
1261 * CertificateList ::= SEQUENCE {
1262 * tbsCertList TBSCertList,
1263 * signatureAlgorithm AlgorithmIdentifier,
1264 * signatureValue BIT STRING }
1265 */
1266 if( ( ret = asn1_get_tag( &p, end, &len,
1267 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1268 {
1269 x509_crl_free( crl );
1270 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT );
1271 }
1272
1273 if( len != (int) ( end - p ) )
1274 {
1275 x509_crl_free( crl );
1276 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT |
1277 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
1278 }
1279
1280 /*
1281 * TBSCertList ::= SEQUENCE {
1282 */
1283 crl->tbs.p = p;
1284
1285 if( ( ret = asn1_get_tag( &p, end, &len,
1286 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1287 {
1288 x509_crl_free( crl );
1289 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
1290 }
1291
1292 end = p + len;
1293 crl->tbs.len = end - crl->tbs.p;
1294
1295 /*
1296 * Version ::= INTEGER OPTIONAL { v1(0), v2(1) }
1297 * -- if present, MUST be v2
1298 *
1299 * signature AlgorithmIdentifier
1300 */
1301 if( ( ret = x509_get_version( &p, end, &crl->version ) ) != 0 ||
1302 ( ret = x509_get_alg( &p, end, &crl->sig_oid1 ) ) != 0 )
1303 {
1304 x509_crl_free( crl );
1305 return( ret );
1306 }
1307
1308 crl->version++;
1309
1310 if( crl->version > 2 )
1311 {
1312 x509_crl_free( crl );
1313 return( POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION );
1314 }
1315
1316 if( crl->sig_oid1.len != 9 ||
1317 memcmp( crl->sig_oid1.p, OID_PKCS1, 8 ) != 0 )
1318 {
1319 x509_crl_free( crl );
1320 return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
1321 }
1322
1323 if( crl->sig_oid1.p[8] < 2 ||
1324 ( crl->sig_oid1.p[8] > 5 && crl->sig_oid1.p[8] < 11 ) ||
1325 crl->sig_oid1.p[8] > 14 )
1326 {
1327 x509_crl_free( crl );
1328 return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
1329 }
1330
1331 /*
1332 * issuer Name
1333 */
1334 crl->issuer_raw.p = p;
1335
1336 if( ( ret = asn1_get_tag( &p, end, &len,
1337 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1338 {
1339 x509_crl_free( crl );
1340 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
1341 }
1342
1343 if( ( ret = x509_get_name( &p, p + len, &crl->issuer ) ) != 0 )
1344 {
1345 x509_crl_free( crl );
1346 return( ret );
1347 }
1348
1349 crl->issuer_raw.len = p - crl->issuer_raw.p;
1350
1351 /*
1352 * thisUpdate Time
1353 * nextUpdate Time OPTIONAL
1354 */
Paul Bakker91200182010-02-18 21:26:15 +00001355 if( ( ret = x509_get_time( &p, end, &crl->this_update ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +00001356 {
1357 x509_crl_free( crl );
1358 return( ret );
1359 }
1360
Paul Bakker91200182010-02-18 21:26:15 +00001361 if( ( ret = x509_get_time( &p, end, &crl->next_update ) ) != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +00001362 {
Paul Bakker635f4b42009-07-20 20:34:41 +00001363 if ( ret != ( POLARSSL_ERR_X509_CERT_INVALID_DATE |
Paul Bakker9be19372009-07-27 20:21:53 +00001364 POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) &&
1365 ret != ( POLARSSL_ERR_X509_CERT_INVALID_DATE |
1366 POLARSSL_ERR_ASN1_OUT_OF_DATA ) )
Paul Bakker635f4b42009-07-20 20:34:41 +00001367 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00001368 x509_crl_free( crl );
1369 return( ret );
1370 }
1371 }
1372
1373 /*
1374 * revokedCertificates SEQUENCE OF SEQUENCE {
1375 * userCertificate CertificateSerialNumber,
1376 * revocationDate Time,
1377 * crlEntryExtensions Extensions OPTIONAL
1378 * -- if present, MUST be v2
1379 * } OPTIONAL
1380 */
1381 if( ( ret = x509_get_entries( &p, end, &crl->entry ) ) != 0 )
1382 {
1383 x509_crl_free( crl );
1384 return( ret );
1385 }
1386
1387 /*
1388 * crlExtensions EXPLICIT Extensions OPTIONAL
1389 * -- if present, MUST be v2
1390 */
1391 if( crl->version == 2 )
1392 {
1393 ret = x509_get_crl_ext( &p, end, &crl->crl_ext );
1394
1395 if( ret != 0 )
1396 {
1397 x509_crl_free( crl );
1398 return( ret );
1399 }
1400 }
1401
1402 if( p != end )
1403 {
1404 x509_crl_free( crl );
1405 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT |
1406 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
1407 }
1408
1409 end = crl->raw.p + crl->raw.len;
1410
1411 /*
1412 * signatureAlgorithm AlgorithmIdentifier,
1413 * signatureValue BIT STRING
1414 */
1415 if( ( ret = x509_get_alg( &p, end, &crl->sig_oid2 ) ) != 0 )
1416 {
1417 x509_crl_free( crl );
1418 return( ret );
1419 }
1420
1421 if( memcmp( crl->sig_oid1.p, crl->sig_oid2.p, crl->sig_oid1.len ) != 0 )
1422 {
1423 x509_crl_free( crl );
1424 return( POLARSSL_ERR_X509_CERT_SIG_MISMATCH );
1425 }
1426
1427 if( ( ret = x509_get_sig( &p, end, &crl->sig ) ) != 0 )
1428 {
1429 x509_crl_free( crl );
1430 return( ret );
1431 }
1432
1433 if( p != end )
1434 {
1435 x509_crl_free( crl );
1436 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT |
1437 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
1438 }
1439
1440 if( buflen > 0 )
1441 {
1442 crl->next = (x509_crl *) malloc( sizeof( x509_crl ) );
1443
Paul Bakker7d06ad22009-05-02 15:53:56 +00001444 if( crl->next == NULL )
1445 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00001446 x509_crl_free( crl );
Paul Bakker7d06ad22009-05-02 15:53:56 +00001447 return( 1 );
1448 }
Paul Bakkerd98030e2009-05-02 15:13:40 +00001449
Paul Bakker7d06ad22009-05-02 15:53:56 +00001450 crl = crl->next;
1451 memset( crl, 0, sizeof( x509_crl ) );
Paul Bakkerd98030e2009-05-02 15:13:40 +00001452
1453 return( x509parse_crl( crl, buf, buflen ) );
1454 }
1455
1456 return( 0 );
1457}
1458
1459/*
Paul Bakker2b245eb2009-04-19 18:44:26 +00001460 * Load all data from a file into a given buffer.
1461 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001462int load_file( const char *path, unsigned char **buf, size_t *n )
Paul Bakker2b245eb2009-04-19 18:44:26 +00001463{
Paul Bakkerd98030e2009-05-02 15:13:40 +00001464 FILE *f;
Paul Bakker2b245eb2009-04-19 18:44:26 +00001465
Paul Bakkerd98030e2009-05-02 15:13:40 +00001466 if( ( f = fopen( path, "rb" ) ) == NULL )
1467 return( 1 );
Paul Bakker2b245eb2009-04-19 18:44:26 +00001468
Paul Bakkerd98030e2009-05-02 15:13:40 +00001469 fseek( f, 0, SEEK_END );
1470 *n = (size_t) ftell( f );
1471 fseek( f, 0, SEEK_SET );
Paul Bakker2b245eb2009-04-19 18:44:26 +00001472
Paul Bakkerd98030e2009-05-02 15:13:40 +00001473 if( ( *buf = (unsigned char *) malloc( *n + 1 ) ) == NULL )
1474 return( 1 );
Paul Bakker2b245eb2009-04-19 18:44:26 +00001475
Paul Bakkerd98030e2009-05-02 15:13:40 +00001476 if( fread( *buf, 1, *n, f ) != *n )
1477 {
1478 fclose( f );
1479 free( *buf );
1480 return( 1 );
1481 }
Paul Bakker2b245eb2009-04-19 18:44:26 +00001482
Paul Bakkerd98030e2009-05-02 15:13:40 +00001483 fclose( f );
Paul Bakker2b245eb2009-04-19 18:44:26 +00001484
Paul Bakkerd98030e2009-05-02 15:13:40 +00001485 (*buf)[*n] = '\0';
Paul Bakker2b245eb2009-04-19 18:44:26 +00001486
Paul Bakkerd98030e2009-05-02 15:13:40 +00001487 return( 0 );
Paul Bakker2b245eb2009-04-19 18:44:26 +00001488}
1489
1490/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001491 * Load one or more certificates and add them to the chained list
1492 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001493int x509parse_crtfile( x509_cert *chain, const char *path )
Paul Bakker5121ce52009-01-03 21:22:43 +00001494{
1495 int ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001496 size_t n;
1497 unsigned char *buf;
1498
Paul Bakker2b245eb2009-04-19 18:44:26 +00001499 if ( load_file( path, &buf, &n ) )
Paul Bakker5121ce52009-01-03 21:22:43 +00001500 return( 1 );
1501
Paul Bakker5121ce52009-01-03 21:22:43 +00001502 ret = x509parse_crt( chain, buf, (int) n );
1503
1504 memset( buf, 0, n + 1 );
1505 free( buf );
Paul Bakker5121ce52009-01-03 21:22:43 +00001506
1507 return( ret );
1508}
1509
Paul Bakkerd98030e2009-05-02 15:13:40 +00001510/*
1511 * Load one or more CRLs and add them to the chained list
1512 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001513int x509parse_crlfile( x509_crl *chain, const char *path )
Paul Bakkerd98030e2009-05-02 15:13:40 +00001514{
1515 int ret;
1516 size_t n;
1517 unsigned char *buf;
1518
1519 if ( load_file( path, &buf, &n ) )
1520 return( 1 );
1521
1522 ret = x509parse_crl( chain, buf, (int) n );
1523
1524 memset( buf, 0, n + 1 );
1525 free( buf );
1526
1527 return( ret );
1528}
1529
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00001530#if defined(POLARSSL_DES_C) && defined(POLARSSL_MD5_C)
Paul Bakker5121ce52009-01-03 21:22:43 +00001531/*
1532 * Read a 16-byte hex string and convert it to binary
1533 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001534static int x509_get_iv( const unsigned char *s, unsigned char iv[8] )
Paul Bakker5121ce52009-01-03 21:22:43 +00001535{
1536 int i, j, k;
1537
1538 memset( iv, 0, 8 );
1539
1540 for( i = 0; i < 16; i++, s++ )
1541 {
1542 if( *s >= '0' && *s <= '9' ) j = *s - '0'; else
1543 if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else
1544 if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else
Paul Bakker40e46942009-01-03 21:51:57 +00001545 return( POLARSSL_ERR_X509_KEY_INVALID_ENC_IV );
Paul Bakker5121ce52009-01-03 21:22:43 +00001546
1547 k = ( ( i & 1 ) != 0 ) ? j : j << 4;
1548
1549 iv[i >> 1] = (unsigned char)( iv[i >> 1] | k );
1550 }
1551
1552 return( 0 );
1553}
1554
1555/*
1556 * Decrypt with 3DES-CBC, using PBKDF1 for key derivation
1557 */
1558static void x509_des3_decrypt( unsigned char des3_iv[8],
1559 unsigned char *buf, int buflen,
Paul Bakkerff60ee62010-03-16 21:09:09 +00001560 const unsigned char *pwd, int pwdlen )
Paul Bakker5121ce52009-01-03 21:22:43 +00001561{
1562 md5_context md5_ctx;
1563 des3_context des3_ctx;
1564 unsigned char md5sum[16];
1565 unsigned char des3_key[24];
1566
1567 /*
1568 * 3DES key[ 0..15] = MD5(pwd || IV)
1569 * key[16..23] = MD5(pwd || IV || 3DES key[ 0..15])
1570 */
1571 md5_starts( &md5_ctx );
1572 md5_update( &md5_ctx, pwd, pwdlen );
1573 md5_update( &md5_ctx, des3_iv, 8 );
1574 md5_finish( &md5_ctx, md5sum );
1575 memcpy( des3_key, md5sum, 16 );
1576
1577 md5_starts( &md5_ctx );
1578 md5_update( &md5_ctx, md5sum, 16 );
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 + 16, md5sum, 8 );
1583
1584 des3_set3key_dec( &des3_ctx, des3_key );
1585 des3_crypt_cbc( &des3_ctx, DES_DECRYPT, buflen,
1586 des3_iv, buf, buf );
1587
1588 memset( &md5_ctx, 0, sizeof( md5_ctx ) );
1589 memset( &des3_ctx, 0, sizeof( des3_ctx ) );
1590 memset( md5sum, 0, 16 );
1591 memset( des3_key, 0, 24 );
1592}
1593#endif
1594
1595/*
1596 * Parse a private RSA key
1597 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001598int x509parse_key( rsa_context *rsa, const unsigned char *key, int keylen,
1599 const unsigned char *pwd, int pwdlen )
Paul Bakker5121ce52009-01-03 21:22:43 +00001600{
1601 int ret, len, enc;
Paul Bakkerff60ee62010-03-16 21:09:09 +00001602 unsigned char *buf, *s1, *s2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001603 unsigned char *p, *end;
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00001604#if defined(POLARSSL_DES_C) && defined(POLARSSL_MD5_C)
Paul Bakker5121ce52009-01-03 21:22:43 +00001605 unsigned char des3_iv[8];
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00001606#else
1607 ((void) pwd);
1608 ((void) pwdlen);
1609#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00001610
Paul Bakkerff60ee62010-03-16 21:09:09 +00001611 s1 = (unsigned char *) strstr( (char *) key,
Paul Bakker5121ce52009-01-03 21:22:43 +00001612 "-----BEGIN RSA PRIVATE KEY-----" );
1613
1614 if( s1 != NULL )
1615 {
Paul Bakkerff60ee62010-03-16 21:09:09 +00001616 s2 = (unsigned char *) strstr( (char *) key,
Paul Bakker5121ce52009-01-03 21:22:43 +00001617 "-----END RSA PRIVATE KEY-----" );
1618
1619 if( s2 == NULL || s2 <= s1 )
Paul Bakker40e46942009-01-03 21:51:57 +00001620 return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001621
1622 s1 += 31;
1623 if( *s1 == '\r' ) s1++;
1624 if( *s1 == '\n' ) s1++;
Paul Bakker40e46942009-01-03 21:51:57 +00001625 else return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001626
1627 enc = 0;
1628
1629 if( memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 )
1630 {
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00001631#if defined(POLARSSL_DES_C) && defined(POLARSSL_MD5_C)
Paul Bakker5121ce52009-01-03 21:22:43 +00001632 enc++;
1633
1634 s1 += 22;
1635 if( *s1 == '\r' ) s1++;
1636 if( *s1 == '\n' ) s1++;
Paul Bakker40e46942009-01-03 21:51:57 +00001637 else return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001638
1639 if( memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001640 return( POLARSSL_ERR_X509_KEY_UNKNOWN_ENC_ALG );
Paul Bakker5121ce52009-01-03 21:22:43 +00001641
1642 s1 += 23;
1643 if( x509_get_iv( s1, des3_iv ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001644 return( POLARSSL_ERR_X509_KEY_INVALID_ENC_IV );
Paul Bakker5121ce52009-01-03 21:22:43 +00001645
1646 s1 += 16;
1647 if( *s1 == '\r' ) s1++;
1648 if( *s1 == '\n' ) s1++;
Paul Bakker40e46942009-01-03 21:51:57 +00001649 else return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001650#else
Paul Bakker40e46942009-01-03 21:51:57 +00001651 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001652#endif
1653 }
1654
1655 len = 0;
1656 ret = base64_decode( NULL, &len, s1, s2 - s1 );
1657
Paul Bakker40e46942009-01-03 21:51:57 +00001658 if( ret == POLARSSL_ERR_BASE64_INVALID_CHARACTER )
1659 return( ret | POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001660
1661 if( ( buf = (unsigned char *) malloc( len ) ) == NULL )
1662 return( 1 );
1663
1664 if( ( ret = base64_decode( buf, &len, s1, s2 - s1 ) ) != 0 )
1665 {
1666 free( buf );
Paul Bakker40e46942009-01-03 21:51:57 +00001667 return( ret | POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001668 }
1669
Paul Bakkerff60ee62010-03-16 21:09:09 +00001670 keylen = len;
Paul Bakker5121ce52009-01-03 21:22:43 +00001671
1672 if( enc != 0 )
1673 {
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00001674#if defined(POLARSSL_DES_C) && defined(POLARSSL_MD5_C)
Paul Bakker5121ce52009-01-03 21:22:43 +00001675 if( pwd == NULL )
1676 {
1677 free( buf );
Paul Bakker40e46942009-01-03 21:51:57 +00001678 return( POLARSSL_ERR_X509_KEY_PASSWORD_REQUIRED );
Paul Bakker5121ce52009-01-03 21:22:43 +00001679 }
1680
Paul Bakkerff60ee62010-03-16 21:09:09 +00001681 x509_des3_decrypt( des3_iv, buf, keylen, pwd, pwdlen );
Paul Bakker5121ce52009-01-03 21:22:43 +00001682
1683 if( buf[0] != 0x30 || buf[1] != 0x82 ||
1684 buf[4] != 0x02 || buf[5] != 0x01 )
1685 {
1686 free( buf );
Paul Bakker40e46942009-01-03 21:51:57 +00001687 return( POLARSSL_ERR_X509_KEY_PASSWORD_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001688 }
1689#else
Paul Bakker40e46942009-01-03 21:51:57 +00001690 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001691#endif
1692 }
1693 }
Paul Bakkerff60ee62010-03-16 21:09:09 +00001694 else
1695 {
1696 buf = NULL;
1697 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001698
1699 memset( rsa, 0, sizeof( rsa_context ) );
1700
Paul Bakkerff60ee62010-03-16 21:09:09 +00001701 p = ( s1 != NULL ) ? buf : (unsigned char *) key;
1702 end = p + keylen;
Paul Bakker5121ce52009-01-03 21:22:43 +00001703
1704 /*
1705 * RSAPrivateKey ::= SEQUENCE {
1706 * version Version,
1707 * modulus INTEGER, -- n
1708 * publicExponent INTEGER, -- e
1709 * privateExponent INTEGER, -- d
1710 * prime1 INTEGER, -- p
1711 * prime2 INTEGER, -- q
1712 * exponent1 INTEGER, -- d mod (p-1)
1713 * exponent2 INTEGER, -- d mod (q-1)
1714 * coefficient INTEGER, -- (inverse of q) mod p
1715 * otherPrimeInfos OtherPrimeInfos OPTIONAL
1716 * }
1717 */
1718 if( ( ret = asn1_get_tag( &p, end, &len,
1719 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1720 {
1721 if( s1 != NULL )
1722 free( buf );
1723
1724 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001725 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001726 }
1727
1728 end = p + len;
1729
1730 if( ( ret = asn1_get_int( &p, end, &rsa->ver ) ) != 0 )
1731 {
1732 if( s1 != NULL )
1733 free( buf );
1734
1735 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001736 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001737 }
1738
1739 if( rsa->ver != 0 )
1740 {
1741 if( s1 != NULL )
1742 free( buf );
1743
1744 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001745 return( ret | POLARSSL_ERR_X509_KEY_INVALID_VERSION );
Paul Bakker5121ce52009-01-03 21:22:43 +00001746 }
1747
1748 if( ( ret = asn1_get_mpi( &p, end, &rsa->N ) ) != 0 ||
1749 ( ret = asn1_get_mpi( &p, end, &rsa->E ) ) != 0 ||
1750 ( ret = asn1_get_mpi( &p, end, &rsa->D ) ) != 0 ||
1751 ( ret = asn1_get_mpi( &p, end, &rsa->P ) ) != 0 ||
1752 ( ret = asn1_get_mpi( &p, end, &rsa->Q ) ) != 0 ||
1753 ( ret = asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 ||
1754 ( ret = asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 ||
1755 ( ret = asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 )
1756 {
1757 if( s1 != NULL )
1758 free( buf );
1759
1760 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001761 return( ret | POLARSSL_ERR_X509_KEY_INVALID_FORMAT );
Paul Bakker5121ce52009-01-03 21:22:43 +00001762 }
1763
1764 rsa->len = mpi_size( &rsa->N );
1765
1766 if( p != end )
1767 {
1768 if( s1 != NULL )
1769 free( buf );
1770
1771 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001772 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT |
1773 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001774 }
1775
1776 if( ( ret = rsa_check_privkey( rsa ) ) != 0 )
1777 {
1778 if( s1 != NULL )
1779 free( buf );
1780
1781 rsa_free( rsa );
1782 return( ret );
1783 }
1784
1785 if( s1 != NULL )
1786 free( buf );
1787
1788 return( 0 );
1789}
1790
1791/*
1792 * Load and parse a private RSA key
1793 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001794int x509parse_keyfile( rsa_context *rsa, const char *path, const char *pwd )
Paul Bakker5121ce52009-01-03 21:22:43 +00001795{
1796 int ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001797 size_t n;
1798 unsigned char *buf;
1799
Paul Bakker2b245eb2009-04-19 18:44:26 +00001800 if ( load_file( path, &buf, &n ) )
Paul Bakker5121ce52009-01-03 21:22:43 +00001801 return( 1 );
1802
Paul Bakker5121ce52009-01-03 21:22:43 +00001803 if( pwd == NULL )
1804 ret = x509parse_key( rsa, buf, (int) n, NULL, 0 );
1805 else
1806 ret = x509parse_key( rsa, buf, (int) n,
1807 (unsigned char *) pwd, strlen( pwd ) );
1808
1809 memset( buf, 0, n + 1 );
1810 free( buf );
Paul Bakker5121ce52009-01-03 21:22:43 +00001811
1812 return( ret );
1813}
1814
1815#if defined _MSC_VER && !defined snprintf
Paul Bakkerd98030e2009-05-02 15:13:40 +00001816#include <stdarg.h>
1817
1818#if !defined vsnprintf
1819#define vsnprintf _vsnprintf
1820#endif // vsnprintf
1821
1822/*
1823 * Windows _snprintf and _vsnprintf are not compatible to linux versions.
1824 * Result value is not size of buffer needed, but -1 if no fit is possible.
1825 *
1826 * This fuction tries to 'fix' this by at least suggesting enlarging the
1827 * size by 20.
1828 */
1829int compat_snprintf(char *str, size_t size, const char *format, ...)
1830{
1831 va_list ap;
1832 int res = -1;
1833
1834 va_start( ap, format );
1835
1836 res = vsnprintf( str, size, format, ap );
1837
1838 va_end( ap );
1839
1840 // No quick fix possible
1841 if ( res < 0 )
1842 return( size + 20 );
1843
1844 return res;
1845}
1846
1847#define snprintf compat_snprintf
Paul Bakker5121ce52009-01-03 21:22:43 +00001848#endif
1849
Paul Bakkerd98030e2009-05-02 15:13:40 +00001850#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL -2
1851
1852#define SAFE_SNPRINTF() \
1853{ \
1854 if( ret == -1 ) \
1855 return( -1 ); \
1856 \
1857 if ( ret > n ) { \
1858 p[n - 1] = '\0'; \
1859 return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
1860 } \
1861 \
1862 n -= ret; \
1863 p += ret; \
1864}
1865
Paul Bakker5121ce52009-01-03 21:22:43 +00001866/*
1867 * Store the name in printable form into buf; no more
Paul Bakkerd98030e2009-05-02 15:13:40 +00001868 * than size characters will be written
Paul Bakker5121ce52009-01-03 21:22:43 +00001869 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001870int x509parse_dn_gets( char *buf, size_t size, const x509_name *dn )
Paul Bakker5121ce52009-01-03 21:22:43 +00001871{
Paul Bakkerd98030e2009-05-02 15:13:40 +00001872 int i, ret, n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001873 unsigned char c;
Paul Bakkerff60ee62010-03-16 21:09:09 +00001874 const x509_name *name;
Paul Bakker5121ce52009-01-03 21:22:43 +00001875 char s[128], *p;
1876
1877 memset( s, 0, sizeof( s ) );
1878
1879 name = dn;
1880 p = buf;
Paul Bakkerd98030e2009-05-02 15:13:40 +00001881 n = size;
Paul Bakker5121ce52009-01-03 21:22:43 +00001882
1883 while( name != NULL )
1884 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00001885 if( name != dn ) {
1886 ret = snprintf( p, n, ", " );
1887 SAFE_SNPRINTF();
1888 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001889
1890 if( memcmp( name->oid.p, OID_X520, 2 ) == 0 )
1891 {
1892 switch( name->oid.p[2] )
1893 {
1894 case X520_COMMON_NAME:
Paul Bakkerd98030e2009-05-02 15:13:40 +00001895 ret = snprintf( p, n, "CN=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00001896
1897 case X520_COUNTRY:
Paul Bakkerd98030e2009-05-02 15:13:40 +00001898 ret = snprintf( p, n, "C=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00001899
1900 case X520_LOCALITY:
Paul Bakkerd98030e2009-05-02 15:13:40 +00001901 ret = snprintf( p, n, "L=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00001902
1903 case X520_STATE:
Paul Bakkerd98030e2009-05-02 15:13:40 +00001904 ret = snprintf( p, n, "ST=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00001905
1906 case X520_ORGANIZATION:
Paul Bakkerd98030e2009-05-02 15:13:40 +00001907 ret = snprintf( p, n, "O=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00001908
1909 case X520_ORG_UNIT:
Paul Bakkerd98030e2009-05-02 15:13:40 +00001910 ret = snprintf( p, n, "OU=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00001911
1912 default:
Paul Bakkerd98030e2009-05-02 15:13:40 +00001913 ret = snprintf( p, n, "0x%02X=",
Paul Bakker5121ce52009-01-03 21:22:43 +00001914 name->oid.p[2] );
1915 break;
1916 }
Paul Bakkerd98030e2009-05-02 15:13:40 +00001917 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00001918 }
1919 else if( memcmp( name->oid.p, OID_PKCS9, 8 ) == 0 )
1920 {
1921 switch( name->oid.p[8] )
1922 {
1923 case PKCS9_EMAIL:
Paul Bakkerd98030e2009-05-02 15:13:40 +00001924 ret = snprintf( p, n, "emailAddress=" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00001925
1926 default:
Paul Bakkerd98030e2009-05-02 15:13:40 +00001927 ret = snprintf( p, n, "0x%02X=",
Paul Bakker5121ce52009-01-03 21:22:43 +00001928 name->oid.p[8] );
1929 break;
1930 }
Paul Bakkerd98030e2009-05-02 15:13:40 +00001931 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00001932 }
1933 else
Paul Bakkerd98030e2009-05-02 15:13:40 +00001934 {
1935 ret = snprintf( p, n, "\?\?=" );
1936 SAFE_SNPRINTF();
1937 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001938
1939 for( i = 0; i < name->val.len; i++ )
1940 {
1941 if( i >= (int) sizeof( s ) - 1 )
1942 break;
1943
1944 c = name->val.p[i];
1945 if( c < 32 || c == 127 || ( c > 128 && c < 160 ) )
1946 s[i] = '?';
1947 else s[i] = c;
1948 }
1949 s[i] = '\0';
Paul Bakkerd98030e2009-05-02 15:13:40 +00001950 ret = snprintf( p, n, "%s", s );
1951 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00001952 name = name->next;
1953 }
1954
Paul Bakkerd98030e2009-05-02 15:13:40 +00001955 return( size - n );
Paul Bakker5121ce52009-01-03 21:22:43 +00001956}
1957
1958/*
Paul Bakkerd98030e2009-05-02 15:13:40 +00001959 * Return an informational string about the certificate.
Paul Bakker5121ce52009-01-03 21:22:43 +00001960 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001961int x509parse_cert_info( char *buf, size_t size, const char *prefix,
1962 const x509_cert *crt )
Paul Bakker5121ce52009-01-03 21:22:43 +00001963{
Paul Bakkerd98030e2009-05-02 15:13:40 +00001964 int i, n, nr, ret;
1965 char *p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001966
1967 p = buf;
Paul Bakkerd98030e2009-05-02 15:13:40 +00001968 n = size;
Paul Bakker5121ce52009-01-03 21:22:43 +00001969
Paul Bakkerd98030e2009-05-02 15:13:40 +00001970 ret = snprintf( p, n, "%scert. version : %d\n",
Paul Bakker5121ce52009-01-03 21:22:43 +00001971 prefix, crt->version );
Paul Bakkerd98030e2009-05-02 15:13:40 +00001972 SAFE_SNPRINTF();
1973 ret = snprintf( p, n, "%sserial number : ",
Paul Bakker5121ce52009-01-03 21:22:43 +00001974 prefix );
Paul Bakkerd98030e2009-05-02 15:13:40 +00001975 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00001976
Paul Bakkerd98030e2009-05-02 15:13:40 +00001977 nr = ( crt->serial.len <= 32 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001978 ? crt->serial.len : 32;
1979
Paul Bakkerd98030e2009-05-02 15:13:40 +00001980 for( i = 0; i < nr; i++ )
1981 {
1982 ret = snprintf( p, n, "%02X%s",
1983 crt->serial.p[i], ( i < nr - 1 ) ? ":" : "" );
1984 SAFE_SNPRINTF();
1985 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001986
Paul Bakkerd98030e2009-05-02 15:13:40 +00001987 ret = snprintf( p, n, "\n%sissuer name : ", prefix );
1988 SAFE_SNPRINTF();
1989 ret = x509parse_dn_gets( p, n, &crt->issuer );
1990 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00001991
Paul Bakkerd98030e2009-05-02 15:13:40 +00001992 ret = snprintf( p, n, "\n%ssubject name : ", prefix );
1993 SAFE_SNPRINTF();
1994 ret = x509parse_dn_gets( p, n, &crt->subject );
1995 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00001996
Paul Bakkerd98030e2009-05-02 15:13:40 +00001997 ret = snprintf( p, n, "\n%sissued on : " \
Paul Bakker5121ce52009-01-03 21:22:43 +00001998 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
1999 crt->valid_from.year, crt->valid_from.mon,
2000 crt->valid_from.day, crt->valid_from.hour,
2001 crt->valid_from.min, crt->valid_from.sec );
Paul Bakkerd98030e2009-05-02 15:13:40 +00002002 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002003
Paul Bakkerd98030e2009-05-02 15:13:40 +00002004 ret = snprintf( p, n, "\n%sexpires on : " \
Paul Bakker5121ce52009-01-03 21:22:43 +00002005 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
2006 crt->valid_to.year, crt->valid_to.mon,
2007 crt->valid_to.day, crt->valid_to.hour,
2008 crt->valid_to.min, crt->valid_to.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%ssigned using : RSA+", prefix );
2012 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002013
2014 switch( crt->sig_oid1.p[8] )
2015 {
Paul Bakkerd98030e2009-05-02 15:13:40 +00002016 case SIG_RSA_MD2 : ret = snprintf( p, n, "MD2" ); break;
2017 case SIG_RSA_MD4 : ret = snprintf( p, n, "MD4" ); break;
2018 case SIG_RSA_MD5 : ret = snprintf( p, n, "MD5" ); break;
2019 case SIG_RSA_SHA1 : ret = snprintf( p, n, "SHA1" ); break;
2020 case SIG_RSA_SHA224 : ret = snprintf( p, n, "SHA224" ); break;
2021 case SIG_RSA_SHA256 : ret = snprintf( p, n, "SHA256" ); break;
2022 case SIG_RSA_SHA384 : ret = snprintf( p, n, "SHA384" ); break;
2023 case SIG_RSA_SHA512 : ret = snprintf( p, n, "SHA512" ); break;
2024 default: ret = snprintf( p, n, "???" ); break;
2025 }
2026 SAFE_SNPRINTF();
2027
2028 ret = snprintf( p, n, "\n%sRSA key size : %d bits\n", prefix,
2029 crt->rsa.N.n * (int) sizeof( unsigned long ) * 8 );
2030 SAFE_SNPRINTF();
2031
2032 return( size - n );
2033}
2034
2035/*
2036 * Return an informational string about the CRL.
2037 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00002038int x509parse_crl_info( char *buf, size_t size, const char *prefix,
2039 const x509_crl *crl )
Paul Bakkerd98030e2009-05-02 15:13:40 +00002040{
2041 int i, n, nr, ret;
2042 char *p;
Paul Bakkerff60ee62010-03-16 21:09:09 +00002043 const x509_crl_entry *entry;
Paul Bakkerd98030e2009-05-02 15:13:40 +00002044
2045 p = buf;
2046 n = size;
2047
2048 ret = snprintf( p, n, "%sCRL version : %d",
2049 prefix, crl->version );
2050 SAFE_SNPRINTF();
2051
2052 ret = snprintf( p, n, "\n%sissuer name : ", prefix );
2053 SAFE_SNPRINTF();
2054 ret = x509parse_dn_gets( p, n, &crl->issuer );
2055 SAFE_SNPRINTF();
2056
2057 ret = snprintf( p, n, "\n%sthis update : " \
2058 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
2059 crl->this_update.year, crl->this_update.mon,
2060 crl->this_update.day, crl->this_update.hour,
2061 crl->this_update.min, crl->this_update.sec );
2062 SAFE_SNPRINTF();
2063
2064 ret = snprintf( p, n, "\n%snext update : " \
2065 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
2066 crl->next_update.year, crl->next_update.mon,
2067 crl->next_update.day, crl->next_update.hour,
2068 crl->next_update.min, crl->next_update.sec );
2069 SAFE_SNPRINTF();
2070
2071 entry = &crl->entry;
2072
2073 ret = snprintf( p, n, "\n%sRevoked certificates:",
2074 prefix );
2075 SAFE_SNPRINTF();
2076
Paul Bakker9be19372009-07-27 20:21:53 +00002077 while( entry != NULL && entry->raw.len != 0 )
Paul Bakkerd98030e2009-05-02 15:13:40 +00002078 {
2079 ret = snprintf( p, n, "\n%sserial number: ",
2080 prefix );
2081 SAFE_SNPRINTF();
2082
2083 nr = ( entry->serial.len <= 32 )
2084 ? entry->serial.len : 32;
2085
2086 for( i = 0; i < nr; i++ ) {
2087 ret = snprintf( p, n, "%02X%s",
2088 entry->serial.p[i], ( i < nr - 1 ) ? ":" : "" );
2089 SAFE_SNPRINTF();
2090 }
2091
2092 ret = snprintf( p, n, " revocation date: " \
2093 "%04d-%02d-%02d %02d:%02d:%02d",
2094 entry->revocation_date.year, entry->revocation_date.mon,
2095 entry->revocation_date.day, entry->revocation_date.hour,
2096 entry->revocation_date.min, entry->revocation_date.sec );
2097 SAFE_SNPRINTF();
2098
2099 entry = entry->next;
Paul Bakker5121ce52009-01-03 21:22:43 +00002100 }
2101
Paul Bakkerd98030e2009-05-02 15:13:40 +00002102 ret = snprintf( p, n, "\n%ssigned using : RSA+", prefix );
2103 SAFE_SNPRINTF();
Paul Bakker5121ce52009-01-03 21:22:43 +00002104
Paul Bakkerd98030e2009-05-02 15:13:40 +00002105 switch( crl->sig_oid1.p[8] )
2106 {
2107 case SIG_RSA_MD2 : ret = snprintf( p, n, "MD2" ); break;
2108 case SIG_RSA_MD4 : ret = snprintf( p, n, "MD4" ); break;
2109 case SIG_RSA_MD5 : ret = snprintf( p, n, "MD5" ); break;
2110 case SIG_RSA_SHA1 : ret = snprintf( p, n, "SHA1" ); break;
2111 case SIG_RSA_SHA224 : ret = snprintf( p, n, "SHA224" ); break;
2112 case SIG_RSA_SHA256 : ret = snprintf( p, n, "SHA256" ); break;
2113 case SIG_RSA_SHA384 : ret = snprintf( p, n, "SHA384" ); break;
2114 case SIG_RSA_SHA512 : ret = snprintf( p, n, "SHA512" ); break;
2115 default: ret = snprintf( p, n, "???" ); break;
2116 }
2117 SAFE_SNPRINTF();
2118
Paul Bakker1e27bb22009-07-19 20:25:25 +00002119 ret = snprintf( p, n, "\n" );
2120 SAFE_SNPRINTF();
2121
Paul Bakkerd98030e2009-05-02 15:13:40 +00002122 return( size - n );
Paul Bakker5121ce52009-01-03 21:22:43 +00002123}
2124
2125/*
Paul Bakker40ea7de2009-05-03 10:18:48 +00002126 * Return 0 if the x509_time is still valid, or 1 otherwise.
Paul Bakker5121ce52009-01-03 21:22:43 +00002127 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00002128int x509parse_time_expired( const x509_time *to )
Paul Bakker5121ce52009-01-03 21:22:43 +00002129{
2130 struct tm *lt;
2131 time_t tt;
2132
2133 tt = time( NULL );
2134 lt = localtime( &tt );
2135
Paul Bakker40ea7de2009-05-03 10:18:48 +00002136 if( lt->tm_year > to->year - 1900 )
2137 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002138
Paul Bakker40ea7de2009-05-03 10:18:48 +00002139 if( lt->tm_year == to->year - 1900 &&
2140 lt->tm_mon > to->mon - 1 )
2141 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002142
Paul Bakker40ea7de2009-05-03 10:18:48 +00002143 if( lt->tm_year == to->year - 1900 &&
2144 lt->tm_mon == to->mon - 1 &&
2145 lt->tm_mday > to->day )
2146 return( 1 );
2147
2148 return( 0 );
2149}
2150
2151/*
2152 * Return 1 if the certificate is revoked, or 0 otherwise.
2153 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00002154int x509parse_revoked( const x509_cert *crt, const x509_crl *crl )
Paul Bakker40ea7de2009-05-03 10:18:48 +00002155{
Paul Bakkerff60ee62010-03-16 21:09:09 +00002156 const x509_crl_entry *cur = &crl->entry;
Paul Bakker40ea7de2009-05-03 10:18:48 +00002157
2158 while( cur != NULL && cur->serial.len != 0 )
2159 {
2160 if( memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 )
2161 {
2162 if( x509parse_time_expired( &cur->revocation_date ) )
2163 return( 1 );
2164 }
2165
2166 cur = cur->next;
2167 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002168
2169 return( 0 );
2170}
2171
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002172/*
2173 * Wrapper for x509 hashes.
2174 *
2175 * @param out Buffer to receive the hash (Should be at least 64 bytes)
2176 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00002177static void x509_hash( const unsigned char *in, int len, int alg,
Paul Bakker5121ce52009-01-03 21:22:43 +00002178 unsigned char *out )
2179{
2180 switch( alg )
2181 {
Paul Bakker40e46942009-01-03 21:51:57 +00002182#if defined(POLARSSL_MD2_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00002183 case SIG_RSA_MD2 : md2( in, len, out ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002184#endif
Paul Bakker40e46942009-01-03 21:51:57 +00002185#if defined(POLARSSL_MD4_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00002186 case SIG_RSA_MD4 : md4( in, len, out ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002187#endif
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002188#if defined(POLARSSL_MD5_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00002189 case SIG_RSA_MD5 : md5( in, len, out ); break;
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002190#endif
2191#if defined(POLARSSL_SHA1_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00002192 case SIG_RSA_SHA1 : sha1( in, len, out ); break;
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002193#endif
Paul Bakker4593aea2009-02-09 22:32:35 +00002194#if defined(POLARSSL_SHA2_C)
2195 case SIG_RSA_SHA224 : sha2( in, len, out, 1 ); break;
2196 case SIG_RSA_SHA256 : sha2( in, len, out, 0 ); break;
2197#endif
Paul Bakkerfe1aea72009-10-03 20:09:14 +00002198#if defined(POLARSSL_SHA4_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00002199 case SIG_RSA_SHA384 : sha4( in, len, out, 1 ); break;
2200 case SIG_RSA_SHA512 : sha4( in, len, out, 0 ); break;
2201#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00002202 default:
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002203 memset( out, '\xFF', 64 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002204 break;
2205 }
2206}
2207
2208/*
2209 * Verify the certificate validity
2210 */
2211int x509parse_verify( x509_cert *crt,
2212 x509_cert *trust_ca,
Paul Bakker40ea7de2009-05-03 10:18:48 +00002213 x509_crl *ca_crl,
Paul Bakkerff60ee62010-03-16 21:09:09 +00002214 const char *cn, int *flags )
Paul Bakker5121ce52009-01-03 21:22:43 +00002215{
2216 int cn_len;
2217 int hash_id;
2218 int pathlen;
2219 x509_cert *cur;
2220 x509_name *name;
Paul Bakker4593aea2009-02-09 22:32:35 +00002221 unsigned char hash[64];
Paul Bakker5121ce52009-01-03 21:22:43 +00002222
Paul Bakker40ea7de2009-05-03 10:18:48 +00002223 *flags = 0;
2224
2225 if( x509parse_time_expired( &crt->valid_to ) )
2226 *flags = BADCERT_EXPIRED;
Paul Bakker5121ce52009-01-03 21:22:43 +00002227
2228 if( cn != NULL )
2229 {
2230 name = &crt->subject;
2231 cn_len = strlen( cn );
2232
2233 while( name != NULL )
2234 {
2235 if( memcmp( name->oid.p, OID_CN, 3 ) == 0 &&
2236 memcmp( name->val.p, cn, cn_len ) == 0 &&
2237 name->val.len == cn_len )
2238 break;
2239
2240 name = name->next;
2241 }
2242
2243 if( name == NULL )
2244 *flags |= BADCERT_CN_MISMATCH;
2245 }
2246
2247 *flags |= BADCERT_NOT_TRUSTED;
2248
2249 /*
2250 * Iterate upwards in the given cert chain,
2251 * ignoring any upper cert with CA != TRUE.
2252 */
2253 cur = crt->next;
2254
2255 pathlen = 1;
2256
Paul Bakker7c6d4a42009-03-28 20:35:47 +00002257 while( cur != NULL && cur->version != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002258 {
2259 if( cur->ca_istrue == 0 ||
2260 crt->issuer_raw.len != cur->subject_raw.len ||
2261 memcmp( crt->issuer_raw.p, cur->subject_raw.p,
2262 crt->issuer_raw.len ) != 0 )
2263 {
2264 cur = cur->next;
2265 continue;
2266 }
2267
2268 hash_id = crt->sig_oid1.p[8];
2269
2270 x509_hash( crt->tbs.p, crt->tbs.len, hash_id, hash );
2271
2272 if( rsa_pkcs1_verify( &cur->rsa, RSA_PUBLIC, hash_id,
2273 0, hash, crt->sig.p ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00002274 return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +00002275
2276 pathlen++;
2277
2278 crt = cur;
2279 cur = crt->next;
2280 }
2281
2282 /*
2283 * Atempt to validate topmost cert with our CA chain.
2284 */
Paul Bakker7c6d4a42009-03-28 20:35:47 +00002285 while( trust_ca != NULL && trust_ca->version != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002286 {
2287 if( crt->issuer_raw.len != trust_ca->subject_raw.len ||
2288 memcmp( crt->issuer_raw.p, trust_ca->subject_raw.p,
2289 crt->issuer_raw.len ) != 0 )
2290 {
2291 trust_ca = trust_ca->next;
2292 continue;
2293 }
2294
2295 if( trust_ca->max_pathlen > 0 &&
2296 trust_ca->max_pathlen < pathlen )
2297 break;
2298
2299 hash_id = crt->sig_oid1.p[8];
2300
2301 x509_hash( crt->tbs.p, crt->tbs.len, hash_id, hash );
2302
2303 if( rsa_pkcs1_verify( &trust_ca->rsa, RSA_PUBLIC, hash_id,
2304 0, hash, crt->sig.p ) == 0 )
2305 {
2306 /*
2307 * cert. is signed by a trusted CA
2308 */
2309 *flags &= ~BADCERT_NOT_TRUSTED;
2310 break;
2311 }
2312
2313 trust_ca = trust_ca->next;
2314 }
2315
Paul Bakker40ea7de2009-05-03 10:18:48 +00002316 /*
2317 * TODO: What happens if no CRL is present?
2318 * Suggestion: Revocation state should be unknown if no CRL is present.
2319 * For backwards compatibility this is not yet implemented.
2320 */
2321
2322 /*
2323 * Check if the topmost certificate is revoked if the trusted CA is
2324 * determined.
2325 */
2326 while( trust_ca != NULL && ca_crl != NULL && ca_crl->version != 0 )
2327 {
2328 if( ca_crl->issuer_raw.len != trust_ca->subject_raw.len ||
2329 memcmp( ca_crl->issuer_raw.p, trust_ca->subject_raw.p,
2330 ca_crl->issuer_raw.len ) != 0 )
2331 {
2332 ca_crl = ca_crl->next;
2333 continue;
2334 }
2335
2336 /*
2337 * Check if CRL is correctry signed by the trusted CA
2338 */
2339 hash_id = ca_crl->sig_oid1.p[8];
2340
2341 x509_hash( ca_crl->tbs.p, ca_crl->tbs.len, hash_id, hash );
2342
2343 if( !rsa_pkcs1_verify( &trust_ca->rsa, RSA_PUBLIC, hash_id,
2344 0, hash, ca_crl->sig.p ) == 0 )
2345 {
2346 /*
2347 * CRL is not trusted
2348 */
2349 *flags |= BADCRL_NOT_TRUSTED;
2350 break;
2351 }
2352
2353 /*
2354 * Check for validity of CRL (Do not drop out)
2355 */
2356 if( x509parse_time_expired( &ca_crl->next_update ) )
2357 *flags |= BADCRL_EXPIRED;
2358
2359 /*
2360 * Check if certificate is revoked
2361 */
2362 if( x509parse_revoked(crt, ca_crl) )
2363 {
2364 *flags |= BADCERT_REVOKED;
2365 break;
2366 }
2367
2368 ca_crl = ca_crl->next;
2369 }
2370
Paul Bakker5121ce52009-01-03 21:22:43 +00002371 if( *flags != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00002372 return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +00002373
2374 return( 0 );
2375}
2376
2377/*
2378 * Unallocate all certificate data
2379 */
2380void x509_free( x509_cert *crt )
2381{
2382 x509_cert *cert_cur = crt;
2383 x509_cert *cert_prv;
2384 x509_name *name_cur;
2385 x509_name *name_prv;
2386
2387 if( crt == NULL )
2388 return;
2389
2390 do
2391 {
2392 rsa_free( &cert_cur->rsa );
2393
2394 name_cur = cert_cur->issuer.next;
2395 while( name_cur != NULL )
2396 {
2397 name_prv = name_cur;
2398 name_cur = name_cur->next;
2399 memset( name_prv, 0, sizeof( x509_name ) );
2400 free( name_prv );
2401 }
2402
2403 name_cur = cert_cur->subject.next;
2404 while( name_cur != NULL )
2405 {
2406 name_prv = name_cur;
2407 name_cur = name_cur->next;
2408 memset( name_prv, 0, sizeof( x509_name ) );
2409 free( name_prv );
2410 }
2411
2412 if( cert_cur->raw.p != NULL )
2413 {
2414 memset( cert_cur->raw.p, 0, cert_cur->raw.len );
2415 free( cert_cur->raw.p );
2416 }
2417
2418 cert_cur = cert_cur->next;
2419 }
2420 while( cert_cur != NULL );
2421
2422 cert_cur = crt;
2423 do
2424 {
2425 cert_prv = cert_cur;
2426 cert_cur = cert_cur->next;
2427
2428 memset( cert_prv, 0, sizeof( x509_cert ) );
2429 if( cert_prv != crt )
2430 free( cert_prv );
2431 }
2432 while( cert_cur != NULL );
2433}
2434
Paul Bakkerd98030e2009-05-02 15:13:40 +00002435/*
2436 * Unallocate all CRL data
2437 */
2438void x509_crl_free( x509_crl *crl )
2439{
2440 x509_crl *crl_cur = crl;
2441 x509_crl *crl_prv;
2442 x509_name *name_cur;
2443 x509_name *name_prv;
2444 x509_crl_entry *entry_cur;
2445 x509_crl_entry *entry_prv;
2446
2447 if( crl == NULL )
2448 return;
2449
2450 do
2451 {
2452 name_cur = crl_cur->issuer.next;
2453 while( name_cur != NULL )
2454 {
2455 name_prv = name_cur;
2456 name_cur = name_cur->next;
2457 memset( name_prv, 0, sizeof( x509_name ) );
2458 free( name_prv );
2459 }
2460
2461 entry_cur = crl_cur->entry.next;
2462 while( entry_cur != NULL )
2463 {
2464 entry_prv = entry_cur;
2465 entry_cur = entry_cur->next;
2466 memset( entry_prv, 0, sizeof( x509_crl_entry ) );
2467 free( entry_prv );
2468 }
2469
2470 if( crl_cur->raw.p != NULL )
2471 {
2472 memset( crl_cur->raw.p, 0, crl_cur->raw.len );
2473 free( crl_cur->raw.p );
2474 }
2475
2476 crl_cur = crl_cur->next;
2477 }
2478 while( crl_cur != NULL );
2479
2480 crl_cur = crl;
2481 do
2482 {
2483 crl_prv = crl_cur;
2484 crl_cur = crl_cur->next;
2485
2486 memset( crl_prv, 0, sizeof( x509_crl ) );
2487 if( crl_prv != crl )
2488 free( crl_prv );
2489 }
2490 while( crl_cur != NULL );
2491}
2492
Paul Bakker40e46942009-01-03 21:51:57 +00002493#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002494
Paul Bakker40e46942009-01-03 21:51:57 +00002495#include "polarssl/certs.h"
Paul Bakker5121ce52009-01-03 21:22:43 +00002496
2497/*
2498 * Checkup routine
2499 */
2500int x509_self_test( int verbose )
2501{
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002502#if defined(POLARSSL_MD5_C)
Paul Bakker5121ce52009-01-03 21:22:43 +00002503 int ret, i, j;
2504 x509_cert cacert;
2505 x509_cert clicert;
2506 rsa_context rsa;
2507
2508 if( verbose != 0 )
2509 printf( " X.509 certificate load: " );
2510
2511 memset( &clicert, 0, sizeof( x509_cert ) );
2512
2513 ret = x509parse_crt( &clicert, (unsigned char *) test_cli_crt,
2514 strlen( test_cli_crt ) );
2515 if( ret != 0 )
2516 {
2517 if( verbose != 0 )
2518 printf( "failed\n" );
2519
2520 return( ret );
2521 }
2522
2523 memset( &cacert, 0, sizeof( x509_cert ) );
2524
2525 ret = x509parse_crt( &cacert, (unsigned char *) test_ca_crt,
2526 strlen( test_ca_crt ) );
2527 if( ret != 0 )
2528 {
2529 if( verbose != 0 )
2530 printf( "failed\n" );
2531
2532 return( ret );
2533 }
2534
2535 if( verbose != 0 )
2536 printf( "passed\n X.509 private key load: " );
2537
2538 i = strlen( test_ca_key );
2539 j = strlen( test_ca_pwd );
2540
2541 if( ( ret = x509parse_key( &rsa,
2542 (unsigned char *) test_ca_key, i,
2543 (unsigned char *) test_ca_pwd, j ) ) != 0 )
2544 {
2545 if( verbose != 0 )
2546 printf( "failed\n" );
2547
2548 return( ret );
2549 }
2550
2551 if( verbose != 0 )
2552 printf( "passed\n X.509 signature verify: ");
2553
Paul Bakker1973e4c2009-07-10 22:32:40 +00002554 ret = x509parse_verify( &clicert, &cacert, NULL, "PolarSSL Client 2", &i );
Paul Bakker5121ce52009-01-03 21:22:43 +00002555 if( ret != 0 )
2556 {
2557 if( verbose != 0 )
2558 printf( "failed\n" );
2559
2560 return( ret );
2561 }
2562
2563 if( verbose != 0 )
2564 printf( "passed\n\n" );
2565
2566 x509_free( &cacert );
2567 x509_free( &clicert );
2568 rsa_free( &rsa );
2569
2570 return( 0 );
Paul Bakkerde4d2ea2009-10-03 19:58:52 +00002571#else
2572 ((void) verbose);
2573 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
2574#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00002575}
2576
2577#endif
2578
2579#endif