blob: feb4d5074b0d449b0a0b501ed453c112f820355e [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * X.509 certificate and private key decoding
3 *
Paul Bakkere0ccd0a2009-01-04 16:27:10 +00004 * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
5 *
Paul Bakker785a9ee2009-01-25 14:15:10 +00006 * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
Paul Bakker5121ce52009-01-03 21:22:43 +00007 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22/*
23 * The ITU-T X.509 standard defines a certificat format for PKI.
24 *
25 * http://www.ietf.org/rfc/rfc2459.txt
26 * http://www.ietf.org/rfc/rfc3279.txt
27 *
28 * ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
29 *
30 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
31 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
32 */
33
Paul Bakker40e46942009-01-03 21:51:57 +000034#include "polarssl/config.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000035
Paul Bakker40e46942009-01-03 21:51:57 +000036#if defined(POLARSSL_X509_PARSE_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Paul Bakker40e46942009-01-03 21:51:57 +000038#include "polarssl/x509.h"
39#include "polarssl/base64.h"
40#include "polarssl/des.h"
41#include "polarssl/md2.h"
42#include "polarssl/md4.h"
43#include "polarssl/md5.h"
44#include "polarssl/sha1.h"
Paul Bakker026c03b2009-03-28 17:53:03 +000045#include "polarssl/sha2.h"
46#include "polarssl/sha4.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000047
48#include <string.h>
49#include <stdlib.h>
50#include <stdio.h>
51#include <time.h>
52
53/*
54 * ASN.1 DER decoding routines
55 */
56static int asn1_get_len( unsigned char **p,
57 unsigned char *end,
58 int *len )
59{
60 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +000061 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000062
63 if( ( **p & 0x80 ) == 0 )
64 *len = *(*p)++;
65 else
66 {
67 switch( **p & 0x7F )
68 {
69 case 1:
70 if( ( end - *p ) < 2 )
Paul Bakker40e46942009-01-03 21:51:57 +000071 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000072
73 *len = (*p)[1];
74 (*p) += 2;
75 break;
76
77 case 2:
78 if( ( end - *p ) < 3 )
Paul Bakker40e46942009-01-03 21:51:57 +000079 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000080
81 *len = ( (*p)[1] << 8 ) | (*p)[2];
82 (*p) += 3;
83 break;
84
85 default:
Paul Bakker40e46942009-01-03 21:51:57 +000086 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
Paul Bakker5121ce52009-01-03 21:22:43 +000087 break;
88 }
89 }
90
91 if( *len > (int) ( end - *p ) )
Paul Bakker40e46942009-01-03 21:51:57 +000092 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000093
94 return( 0 );
95}
96
97static int asn1_get_tag( unsigned char **p,
98 unsigned char *end,
99 int *len, int tag )
100{
101 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000102 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000103
104 if( **p != tag )
Paul Bakker40e46942009-01-03 21:51:57 +0000105 return( POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000106
107 (*p)++;
108
109 return( asn1_get_len( p, end, len ) );
110}
111
112static int asn1_get_bool( unsigned char **p,
113 unsigned char *end,
114 int *val )
115{
116 int ret, len;
117
118 if( ( ret = asn1_get_tag( p, end, &len, ASN1_BOOLEAN ) ) != 0 )
119 return( ret );
120
121 if( len != 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000122 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000123
124 *val = ( **p != 0 ) ? 1 : 0;
125 (*p)++;
126
127 return( 0 );
128}
129
130static int asn1_get_int( unsigned char **p,
131 unsigned char *end,
132 int *val )
133{
134 int ret, len;
135
136 if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
137 return( ret );
138
139 if( len > (int) sizeof( int ) || ( **p & 0x80 ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000140 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000141
142 *val = 0;
143
144 while( len-- > 0 )
145 {
146 *val = ( *val << 8 ) | **p;
147 (*p)++;
148 }
149
150 return( 0 );
151}
152
153static int asn1_get_mpi( unsigned char **p,
154 unsigned char *end,
155 mpi *X )
156{
157 int ret, len;
158
159 if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
160 return( ret );
161
162 ret = mpi_read_binary( X, *p, len );
163
164 *p += len;
165
166 return( ret );
167}
168
169/*
170 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
171 */
172static int x509_get_version( unsigned char **p,
173 unsigned char *end,
174 int *ver )
175{
176 int ret, len;
177
178 if( ( ret = asn1_get_tag( p, end, &len,
179 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) != 0 )
180 {
Paul Bakker40e46942009-01-03 21:51:57 +0000181 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker5121ce52009-01-03 21:22:43 +0000182 return( *ver = 0 );
183
184 return( ret );
185 }
186
187 end = *p + len;
188
189 if( ( ret = asn1_get_int( p, end, ver ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000190 return( POLARSSL_ERR_X509_CERT_INVALID_VERSION | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000191
192 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000193 return( POLARSSL_ERR_X509_CERT_INVALID_VERSION |
194 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000195
196 return( 0 );
197}
198
199/*
200 * CertificateSerialNumber ::= INTEGER
201 */
202static int x509_get_serial( unsigned char **p,
203 unsigned char *end,
204 x509_buf *serial )
205{
206 int ret;
207
208 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000209 return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL |
210 POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000211
212 if( **p != ( ASN1_CONTEXT_SPECIFIC | ASN1_PRIMITIVE | 2 ) &&
213 **p != ASN1_INTEGER )
Paul Bakker40e46942009-01-03 21:51:57 +0000214 return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL |
215 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000216
217 serial->tag = *(*p)++;
218
219 if( ( ret = asn1_get_len( p, end, &serial->len ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000220 return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000221
222 serial->p = *p;
223 *p += serial->len;
224
225 return( 0 );
226}
227
228/*
229 * AlgorithmIdentifier ::= SEQUENCE {
230 * algorithm OBJECT IDENTIFIER,
231 * parameters ANY DEFINED BY algorithm OPTIONAL }
232 */
233static int x509_get_alg( unsigned char **p,
234 unsigned char *end,
235 x509_buf *alg )
236{
237 int ret, len;
238
239 if( ( ret = asn1_get_tag( p, end, &len,
240 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000241 return( POLARSSL_ERR_X509_CERT_INVALID_ALG | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000242
243 end = *p + len;
244 alg->tag = **p;
245
246 if( ( ret = asn1_get_tag( p, end, &alg->len, ASN1_OID ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000247 return( POLARSSL_ERR_X509_CERT_INVALID_ALG | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000248
249 alg->p = *p;
250 *p += alg->len;
251
252 if( *p == end )
253 return( 0 );
254
255 /*
256 * assume the algorithm parameters must be NULL
257 */
258 if( ( ret = asn1_get_tag( p, end, &len, ASN1_NULL ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000259 return( POLARSSL_ERR_X509_CERT_INVALID_ALG | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000260
261 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000262 return( POLARSSL_ERR_X509_CERT_INVALID_ALG |
263 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000264
265 return( 0 );
266}
267
268/*
269 * RelativeDistinguishedName ::=
270 * SET OF AttributeTypeAndValue
271 *
272 * AttributeTypeAndValue ::= SEQUENCE {
273 * type AttributeType,
274 * value AttributeValue }
275 *
276 * AttributeType ::= OBJECT IDENTIFIER
277 *
278 * AttributeValue ::= ANY DEFINED BY AttributeType
279 */
280static int x509_get_name( unsigned char **p,
281 unsigned char *end,
282 x509_name *cur )
283{
284 int ret, len;
285 unsigned char *end2;
286 x509_buf *oid;
287 x509_buf *val;
288
289 if( ( ret = asn1_get_tag( p, end, &len,
290 ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000291 return( POLARSSL_ERR_X509_CERT_INVALID_NAME | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000292
293 end2 = end;
294 end = *p + len;
295
296 if( ( ret = asn1_get_tag( p, end, &len,
297 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000298 return( POLARSSL_ERR_X509_CERT_INVALID_NAME | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000299
300 if( *p + len != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000301 return( POLARSSL_ERR_X509_CERT_INVALID_NAME |
302 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000303
304 oid = &cur->oid;
305 oid->tag = **p;
306
307 if( ( ret = asn1_get_tag( p, end, &oid->len, ASN1_OID ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000308 return( POLARSSL_ERR_X509_CERT_INVALID_NAME | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000309
310 oid->p = *p;
311 *p += oid->len;
312
313 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000314 return( POLARSSL_ERR_X509_CERT_INVALID_NAME |
315 POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000316
317 if( **p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING &&
318 **p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING &&
319 **p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING )
Paul Bakker40e46942009-01-03 21:51:57 +0000320 return( POLARSSL_ERR_X509_CERT_INVALID_NAME |
321 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000322
323 val = &cur->val;
324 val->tag = *(*p)++;
325
326 if( ( ret = asn1_get_len( p, end, &val->len ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000327 return( POLARSSL_ERR_X509_CERT_INVALID_NAME | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000328
329 val->p = *p;
330 *p += val->len;
331
332 cur->next = NULL;
333
334 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000335 return( POLARSSL_ERR_X509_CERT_INVALID_NAME |
336 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000337
338 /*
339 * recurse until end of SEQUENCE is reached
340 */
341 if( *p == end2 )
342 return( 0 );
343
344 cur->next = (x509_name *) malloc(
345 sizeof( x509_name ) );
346
347 if( cur->next == NULL )
348 return( 1 );
349
350 return( x509_get_name( p, end2, cur->next ) );
351}
352
353/*
354 * Validity ::= SEQUENCE {
355 * notBefore Time,
356 * notAfter Time }
357 *
358 * Time ::= CHOICE {
359 * utcTime UTCTime,
360 * generalTime GeneralizedTime }
361 */
362static int x509_get_dates( unsigned char **p,
363 unsigned char *end,
364 x509_time *from,
365 x509_time *to )
366{
367 int ret, len;
368 char date[64];
369
370 if( ( ret = asn1_get_tag( p, end, &len,
371 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000372 return( POLARSSL_ERR_X509_CERT_INVALID_DATE | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000373
374 end = *p + len;
375
376 /*
377 * TODO: also handle GeneralizedTime
378 */
379 if( ( ret = asn1_get_tag( p, end, &len, ASN1_UTC_TIME ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000380 return( POLARSSL_ERR_X509_CERT_INVALID_DATE | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000381
382 memset( date, 0, sizeof( date ) );
383 memcpy( date, *p, ( len < (int) sizeof( date ) - 1 ) ?
384 len : (int) sizeof( date ) - 1 );
385
386 if( sscanf( date, "%2d%2d%2d%2d%2d%2d",
387 &from->year, &from->mon, &from->day,
388 &from->hour, &from->min, &from->sec ) < 5 )
Paul Bakker40e46942009-01-03 21:51:57 +0000389 return( POLARSSL_ERR_X509_CERT_INVALID_DATE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000390
391 from->year += 100 * ( from->year < 90 );
392 from->year += 1900;
393
394 *p += len;
395
396 if( ( ret = asn1_get_tag( p, end, &len, ASN1_UTC_TIME ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000397 return( POLARSSL_ERR_X509_CERT_INVALID_DATE | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000398
399 memset( date, 0, sizeof( date ) );
400 memcpy( date, *p, ( len < (int) sizeof( date ) - 1 ) ?
401 len : (int) sizeof( date ) - 1 );
402
403 if( sscanf( date, "%2d%2d%2d%2d%2d%2d",
404 &to->year, &to->mon, &to->day,
405 &to->hour, &to->min, &to->sec ) < 5 )
Paul Bakker40e46942009-01-03 21:51:57 +0000406 return( POLARSSL_ERR_X509_CERT_INVALID_DATE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000407
408 to->year += 100 * ( to->year < 90 );
409 to->year += 1900;
410
411 *p += len;
412
413 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000414 return( POLARSSL_ERR_X509_CERT_INVALID_DATE |
415 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000416
417 return( 0 );
418}
419
420/*
421 * SubjectPublicKeyInfo ::= SEQUENCE {
422 * algorithm AlgorithmIdentifier,
423 * subjectPublicKey BIT STRING }
424 */
425static int x509_get_pubkey( unsigned char **p,
426 unsigned char *end,
427 x509_buf *pk_alg_oid,
428 mpi *N, mpi *E )
429{
430 int ret, len;
431 unsigned char *end2;
432
433 if( ( ret = x509_get_alg( p, end, pk_alg_oid ) ) != 0 )
434 return( ret );
435
436 /*
437 * only RSA public keys handled at this time
438 */
439 if( pk_alg_oid->len != 9 ||
440 memcmp( pk_alg_oid->p, OID_PKCS1_RSA, 9 ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000441 return( POLARSSL_ERR_X509_CERT_UNKNOWN_PK_ALG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000442
443 if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000444 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000445
446 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000447 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY |
448 POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000449
450 end2 = *p + len;
451
452 if( *(*p)++ != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000453 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY );
Paul Bakker5121ce52009-01-03 21:22:43 +0000454
455 /*
456 * RSAPublicKey ::= SEQUENCE {
457 * modulus INTEGER, -- n
458 * publicExponent INTEGER -- e
459 * }
460 */
461 if( ( ret = asn1_get_tag( p, end2, &len,
462 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000463 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000464
465 if( *p + len != end2 )
Paul Bakker40e46942009-01-03 21:51:57 +0000466 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY |
467 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000468
469 if( ( ret = asn1_get_mpi( p, end2, N ) ) != 0 ||
470 ( ret = asn1_get_mpi( p, end2, E ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000471 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000472
473 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000474 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY |
475 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000476
477 return( 0 );
478}
479
480static int x509_get_sig( unsigned char **p,
481 unsigned char *end,
482 x509_buf *sig )
483{
484 int ret, len;
485
486 sig->tag = **p;
487
488 if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000489 return( POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000490
491 if( --len < 1 || *(*p)++ != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000492 return( POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000493
494 sig->len = len;
495 sig->p = *p;
496
497 *p += len;
498
499 return( 0 );
500}
501
502/*
503 * X.509 v2/v3 unique identifier (not parsed)
504 */
505static int x509_get_uid( unsigned char **p,
506 unsigned char *end,
507 x509_buf *uid, int n )
508{
509 int ret;
510
511 if( *p == end )
512 return( 0 );
513
514 uid->tag = **p;
515
516 if( ( ret = asn1_get_tag( p, end, &uid->len,
517 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | n ) ) != 0 )
518 {
Paul Bakker40e46942009-01-03 21:51:57 +0000519 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker5121ce52009-01-03 21:22:43 +0000520 return( 0 );
521
522 return( ret );
523 }
524
525 uid->p = *p;
526 *p += uid->len;
527
528 return( 0 );
529}
530
531/*
532 * X.509 v3 extensions (only BasicConstraints are parsed)
533 */
534static int x509_get_ext( unsigned char **p,
535 unsigned char *end,
536 x509_buf *ext,
537 int *ca_istrue,
538 int *max_pathlen )
539{
540 int ret, len;
541 int is_critical = 1;
542 int is_cacert = 0;
543 unsigned char *end2;
544
545 if( *p == end )
546 return( 0 );
547
548 ext->tag = **p;
549
550 if( ( ret = asn1_get_tag( p, end, &ext->len,
551 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) ) != 0 )
552 {
Paul Bakker40e46942009-01-03 21:51:57 +0000553 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker5121ce52009-01-03 21:22:43 +0000554 return( 0 );
555
556 return( ret );
557 }
558
559 ext->p = *p;
560 end = *p + ext->len;
561
562 /*
563 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
564 *
565 * Extension ::= SEQUENCE {
566 * extnID OBJECT IDENTIFIER,
567 * critical BOOLEAN DEFAULT FALSE,
568 * extnValue OCTET STRING }
569 */
570 if( ( ret = asn1_get_tag( p, end, &len,
571 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000572 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000573
574 if( end != *p + len )
Paul Bakker40e46942009-01-03 21:51:57 +0000575 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
576 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000577
578 while( *p < end )
579 {
580 if( ( ret = asn1_get_tag( p, end, &len,
581 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000582 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000583
584 if( memcmp( *p, "\x06\x03\x55\x1D\x13", 5 ) != 0 )
585 {
586 *p += len;
587 continue;
588 }
589
590 *p += 5;
591
592 if( ( ret = asn1_get_bool( p, end, &is_critical ) ) != 0 &&
Paul Bakker40e46942009-01-03 21:51:57 +0000593 ( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) )
594 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000595
596 if( ( ret = asn1_get_tag( p, end, &len,
597 ASN1_OCTET_STRING ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000598 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000599
600 /*
601 * BasicConstraints ::= SEQUENCE {
602 * cA BOOLEAN DEFAULT FALSE,
603 * pathLenConstraint INTEGER (0..MAX) OPTIONAL }
604 */
605 end2 = *p + len;
606
607 if( ( ret = asn1_get_tag( p, end2, &len,
608 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000609 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000610
611 if( *p == end2 )
612 continue;
613
614 if( ( ret = asn1_get_bool( p, end2, &is_cacert ) ) != 0 )
615 {
Paul Bakker40e46942009-01-03 21:51:57 +0000616 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker5121ce52009-01-03 21:22:43 +0000617 ret = asn1_get_int( p, end2, &is_cacert );
618
619 if( ret != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000620 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000621
622 if( is_cacert != 0 )
623 is_cacert = 1;
624 }
625
626 if( *p == end2 )
627 continue;
628
629 if( ( ret = asn1_get_int( p, end2, max_pathlen ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000630 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000631
632 if( *p != end2 )
Paul Bakker40e46942009-01-03 21:51:57 +0000633 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
634 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000635
636 max_pathlen++;
637 }
638
639 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000640 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
641 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000642
643 *ca_istrue = is_critical & is_cacert;
644
645 return( 0 );
646}
647
648/*
649 * Parse one or more certificates and add them to the chained list
650 */
651int x509parse_crt( x509_cert *chain, unsigned char *buf, int buflen )
652{
653 int ret, len;
654 unsigned char *s1, *s2;
655 unsigned char *p, *end;
656 x509_cert *crt;
657
658 crt = chain;
659
Paul Bakker320a4b52009-03-28 18:52:39 +0000660 /*
661 * Check for valid input
662 */
663 if( crt == NULL || buf == NULL )
664 return( 1 );
665
Paul Bakkere9581d62009-03-28 20:29:25 +0000666 while( crt->version != 0 && crt->next != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000667 crt = crt->next;
668
669 /*
Paul Bakker320a4b52009-03-28 18:52:39 +0000670 * Add new certificate on the end of the chain if needed.
671 */
Paul Bakkere9581d62009-03-28 20:29:25 +0000672 if ( crt->version != 0 && crt->next == NULL)
Paul Bakker320a4b52009-03-28 18:52:39 +0000673 {
674 crt->next = (x509_cert *) malloc( sizeof( x509_cert ) );
675
676 if( crt->next == NULL )
677 {
678 x509_free( crt );
679 return( 1 );
680 }
681
682 crt = crt->next;
683 memset( crt, 0, sizeof( x509_cert ) );
684 }
685
686 /*
Paul Bakker5121ce52009-01-03 21:22:43 +0000687 * check if the certificate is encoded in base64
688 */
689 s1 = (unsigned char *) strstr( (char *) buf,
690 "-----BEGIN CERTIFICATE-----" );
691
692 if( s1 != NULL )
693 {
694 s2 = (unsigned char *) strstr( (char *) buf,
695 "-----END CERTIFICATE-----" );
696
697 if( s2 == NULL || s2 <= s1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000698 return( POLARSSL_ERR_X509_CERT_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +0000699
700 s1 += 27;
701 if( *s1 == '\r' ) s1++;
702 if( *s1 == '\n' ) s1++;
Paul Bakker40e46942009-01-03 21:51:57 +0000703 else return( POLARSSL_ERR_X509_CERT_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +0000704
705 /*
706 * get the DER data length and decode the buffer
707 */
708 len = 0;
709 ret = base64_decode( NULL, &len, s1, s2 - s1 );
710
Paul Bakker40e46942009-01-03 21:51:57 +0000711 if( ret == POLARSSL_ERR_BASE64_INVALID_CHARACTER )
712 return( POLARSSL_ERR_X509_CERT_INVALID_PEM | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000713
714 if( ( p = (unsigned char *) malloc( len ) ) == NULL )
715 return( 1 );
716
717 if( ( ret = base64_decode( p, &len, s1, s2 - s1 ) ) != 0 )
718 {
719 free( p );
Paul Bakker40e46942009-01-03 21:51:57 +0000720 return( POLARSSL_ERR_X509_CERT_INVALID_PEM | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000721 }
722
723 /*
724 * update the buffer size and offset
725 */
726 s2 += 25;
727 if( *s2 == '\r' ) s2++;
728 if( *s2 == '\n' ) s2++;
729 else
730 {
731 free( p );
Paul Bakker40e46942009-01-03 21:51:57 +0000732 return( POLARSSL_ERR_X509_CERT_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +0000733 }
734
735 buflen -= s2 - buf;
736 buf = s2;
737 }
738 else
739 {
740 /*
741 * nope, copy the raw DER data
742 */
743 p = (unsigned char *) malloc( len = buflen );
744
745 if( p == NULL )
746 return( 1 );
747
748 memcpy( p, buf, buflen );
749
750 buflen = 0;
751 }
752
753 crt->raw.p = p;
754 crt->raw.len = len;
755 end = p + len;
756
757 /*
758 * Certificate ::= SEQUENCE {
759 * tbsCertificate TBSCertificate,
760 * signatureAlgorithm AlgorithmIdentifier,
761 * signatureValue BIT STRING }
762 */
763 if( ( ret = asn1_get_tag( &p, end, &len,
764 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
765 {
766 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000767 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT );
Paul Bakker5121ce52009-01-03 21:22:43 +0000768 }
769
770 if( len != (int) ( end - p ) )
771 {
772 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000773 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT |
774 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000775 }
776
777 /*
778 * TBSCertificate ::= SEQUENCE {
779 */
780 crt->tbs.p = p;
781
782 if( ( ret = asn1_get_tag( &p, end, &len,
783 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
784 {
785 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000786 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000787 }
788
789 end = p + len;
790 crt->tbs.len = end - crt->tbs.p;
791
792 /*
793 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
794 *
795 * CertificateSerialNumber ::= INTEGER
796 *
797 * signature AlgorithmIdentifier
798 */
799 if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 ||
800 ( ret = x509_get_serial( &p, end, &crt->serial ) ) != 0 ||
801 ( ret = x509_get_alg( &p, end, &crt->sig_oid1 ) ) != 0 )
802 {
803 x509_free( crt );
804 return( ret );
805 }
806
807 crt->version++;
808
809 if( crt->version > 3 )
810 {
811 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000812 return( POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION );
Paul Bakker5121ce52009-01-03 21:22:43 +0000813 }
814
815 if( crt->sig_oid1.len != 9 ||
816 memcmp( crt->sig_oid1.p, OID_PKCS1, 8 ) != 0 )
817 {
818 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000819 return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000820 }
821
822 if( crt->sig_oid1.p[8] < 2 ||
Paul Bakker4593aea2009-02-09 22:32:35 +0000823 ( crt->sig_oid1.p[8] > 5 && crt->sig_oid1.p[8] < 11 ) ||
824 crt->sig_oid1.p[8] > 14 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000825 {
826 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000827 return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000828 }
829
830 /*
831 * issuer Name
832 */
833 crt->issuer_raw.p = p;
834
835 if( ( ret = asn1_get_tag( &p, end, &len,
836 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
837 {
838 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000839 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000840 }
841
842 if( ( ret = x509_get_name( &p, p + len, &crt->issuer ) ) != 0 )
843 {
844 x509_free( crt );
845 return( ret );
846 }
847
848 crt->issuer_raw.len = p - crt->issuer_raw.p;
849
850 /*
851 * Validity ::= SEQUENCE {
852 * notBefore Time,
853 * notAfter Time }
854 *
855 */
856 if( ( ret = x509_get_dates( &p, end, &crt->valid_from,
857 &crt->valid_to ) ) != 0 )
858 {
859 x509_free( crt );
860 return( ret );
861 }
862
863 /*
864 * subject Name
865 */
866 crt->subject_raw.p = p;
867
868 if( ( ret = asn1_get_tag( &p, end, &len,
869 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
870 {
871 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000872 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000873 }
874
875 if( ( ret = x509_get_name( &p, p + len, &crt->subject ) ) != 0 )
876 {
877 x509_free( crt );
878 return( ret );
879 }
880
881 crt->subject_raw.len = p - crt->subject_raw.p;
882
883 /*
884 * SubjectPublicKeyInfo ::= SEQUENCE
885 * algorithm AlgorithmIdentifier,
886 * subjectPublicKey BIT STRING }
887 */
888 if( ( ret = asn1_get_tag( &p, end, &len,
889 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
890 {
891 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000892 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000893 }
894
895 if( ( ret = x509_get_pubkey( &p, p + len, &crt->pk_oid,
896 &crt->rsa.N, &crt->rsa.E ) ) != 0 )
897 {
898 x509_free( crt );
899 return( ret );
900 }
901
902 if( ( ret = rsa_check_pubkey( &crt->rsa ) ) != 0 )
903 {
904 x509_free( crt );
905 return( ret );
906 }
907
908 crt->rsa.len = mpi_size( &crt->rsa.N );
909
910 /*
911 * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
912 * -- If present, version shall be v2 or v3
913 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
914 * -- If present, version shall be v2 or v3
915 * extensions [3] EXPLICIT Extensions OPTIONAL
916 * -- If present, version shall be v3
917 */
918 if( crt->version == 2 || crt->version == 3 )
919 {
920 ret = x509_get_uid( &p, end, &crt->issuer_id, 1 );
921 if( ret != 0 )
922 {
923 x509_free( crt );
924 return( ret );
925 }
926 }
927
928 if( crt->version == 2 || crt->version == 3 )
929 {
930 ret = x509_get_uid( &p, end, &crt->subject_id, 2 );
931 if( ret != 0 )
932 {
933 x509_free( crt );
934 return( ret );
935 }
936 }
937
938 if( crt->version == 3 )
939 {
940 ret = x509_get_ext( &p, end, &crt->v3_ext,
941 &crt->ca_istrue, &crt->max_pathlen );
942 if( ret != 0 )
943 {
944 x509_free( crt );
945 return( ret );
946 }
947 }
948
949 if( p != end )
950 {
951 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000952 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT |
953 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000954 }
955
956 end = crt->raw.p + crt->raw.len;
957
958 /*
959 * signatureAlgorithm AlgorithmIdentifier,
960 * signatureValue BIT STRING
961 */
962 if( ( ret = x509_get_alg( &p, end, &crt->sig_oid2 ) ) != 0 )
963 {
964 x509_free( crt );
965 return( ret );
966 }
967
Paul Bakker320a4b52009-03-28 18:52:39 +0000968 if( memcmp( crt->sig_oid1.p, crt->sig_oid2.p, crt->sig_oid1.len ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000969 {
970 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000971 return( POLARSSL_ERR_X509_CERT_SIG_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000972 }
973
974 if( ( ret = x509_get_sig( &p, end, &crt->sig ) ) != 0 )
975 {
976 x509_free( crt );
977 return( ret );
978 }
979
980 if( p != end )
981 {
982 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000983 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT |
984 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000985 }
986
Paul Bakker5121ce52009-01-03 21:22:43 +0000987 if( buflen > 0 )
Paul Bakker320a4b52009-03-28 18:52:39 +0000988 {
989 crt->next = (x509_cert *) malloc( sizeof( x509_cert ) );
990
991 if( crt->next == NULL )
992 {
993 x509_free( crt );
994 return( 1 );
995 }
996
997 crt = crt->next;
998 memset( crt, 0, sizeof( x509_cert ) );
999
Paul Bakker5121ce52009-01-03 21:22:43 +00001000 return( x509parse_crt( crt, buf, buflen ) );
Paul Bakker320a4b52009-03-28 18:52:39 +00001001 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001002
1003 return( 0 );
1004}
1005
1006/*
Paul Bakker2b245eb2009-04-19 18:44:26 +00001007 * Load all data from a file into a given buffer.
1008 */
1009int load_file( char *path, unsigned char **buf, size_t *n )
1010{
1011 FILE *f;
1012
1013 if( ( f = fopen( path, "rb" ) ) == NULL )
1014 return( 1 );
1015
1016 fseek( f, 0, SEEK_END );
1017 *n = (size_t) ftell( f );
1018 fseek( f, 0, SEEK_SET );
1019
1020 if( ( *buf = (unsigned char *) malloc( *n + 1 ) ) == NULL )
1021 return( 1 );
1022
1023 if( fread( *buf, 1, *n, f ) != *n )
1024 {
1025 fclose( f );
1026 free( *buf );
1027 return( 1 );
1028 }
1029
1030 fclose( f );
1031
1032 (*buf)[*n] = '\0';
1033
1034 return( 0 );
1035}
1036
1037/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001038 * Load one or more certificates and add them to the chained list
1039 */
1040int x509parse_crtfile( x509_cert *chain, char *path )
1041{
1042 int ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001043 size_t n;
1044 unsigned char *buf;
1045
Paul Bakker2b245eb2009-04-19 18:44:26 +00001046 if ( load_file( path, &buf, &n ) )
Paul Bakker5121ce52009-01-03 21:22:43 +00001047 return( 1 );
1048
Paul Bakker5121ce52009-01-03 21:22:43 +00001049 ret = x509parse_crt( chain, buf, (int) n );
1050
1051 memset( buf, 0, n + 1 );
1052 free( buf );
Paul Bakker5121ce52009-01-03 21:22:43 +00001053
1054 return( ret );
1055}
1056
Paul Bakker40e46942009-01-03 21:51:57 +00001057#if defined(POLARSSL_DES_C)
Paul Bakker5121ce52009-01-03 21:22:43 +00001058/*
1059 * Read a 16-byte hex string and convert it to binary
1060 */
1061static int x509_get_iv( unsigned char *s, unsigned char iv[8] )
1062{
1063 int i, j, k;
1064
1065 memset( iv, 0, 8 );
1066
1067 for( i = 0; i < 16; i++, s++ )
1068 {
1069 if( *s >= '0' && *s <= '9' ) j = *s - '0'; else
1070 if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else
1071 if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else
Paul Bakker40e46942009-01-03 21:51:57 +00001072 return( POLARSSL_ERR_X509_KEY_INVALID_ENC_IV );
Paul Bakker5121ce52009-01-03 21:22:43 +00001073
1074 k = ( ( i & 1 ) != 0 ) ? j : j << 4;
1075
1076 iv[i >> 1] = (unsigned char)( iv[i >> 1] | k );
1077 }
1078
1079 return( 0 );
1080}
1081
1082/*
1083 * Decrypt with 3DES-CBC, using PBKDF1 for key derivation
1084 */
1085static void x509_des3_decrypt( unsigned char des3_iv[8],
1086 unsigned char *buf, int buflen,
1087 unsigned char *pwd, int pwdlen )
1088{
1089 md5_context md5_ctx;
1090 des3_context des3_ctx;
1091 unsigned char md5sum[16];
1092 unsigned char des3_key[24];
1093
1094 /*
1095 * 3DES key[ 0..15] = MD5(pwd || IV)
1096 * key[16..23] = MD5(pwd || IV || 3DES key[ 0..15])
1097 */
1098 md5_starts( &md5_ctx );
1099 md5_update( &md5_ctx, pwd, pwdlen );
1100 md5_update( &md5_ctx, des3_iv, 8 );
1101 md5_finish( &md5_ctx, md5sum );
1102 memcpy( des3_key, md5sum, 16 );
1103
1104 md5_starts( &md5_ctx );
1105 md5_update( &md5_ctx, md5sum, 16 );
1106 md5_update( &md5_ctx, pwd, pwdlen );
1107 md5_update( &md5_ctx, des3_iv, 8 );
1108 md5_finish( &md5_ctx, md5sum );
1109 memcpy( des3_key + 16, md5sum, 8 );
1110
1111 des3_set3key_dec( &des3_ctx, des3_key );
1112 des3_crypt_cbc( &des3_ctx, DES_DECRYPT, buflen,
1113 des3_iv, buf, buf );
1114
1115 memset( &md5_ctx, 0, sizeof( md5_ctx ) );
1116 memset( &des3_ctx, 0, sizeof( des3_ctx ) );
1117 memset( md5sum, 0, 16 );
1118 memset( des3_key, 0, 24 );
1119}
1120#endif
1121
1122/*
1123 * Parse a private RSA key
1124 */
1125int x509parse_key( rsa_context *rsa, unsigned char *buf, int buflen,
1126 unsigned char *pwd, int pwdlen )
1127{
1128 int ret, len, enc;
1129 unsigned char *s1, *s2;
1130 unsigned char *p, *end;
1131 unsigned char des3_iv[8];
1132
1133 s1 = (unsigned char *) strstr( (char *) buf,
1134 "-----BEGIN RSA PRIVATE KEY-----" );
1135
1136 if( s1 != NULL )
1137 {
1138 s2 = (unsigned char *) strstr( (char *) buf,
1139 "-----END RSA PRIVATE KEY-----" );
1140
1141 if( s2 == NULL || s2 <= s1 )
Paul Bakker40e46942009-01-03 21:51:57 +00001142 return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001143
1144 s1 += 31;
1145 if( *s1 == '\r' ) s1++;
1146 if( *s1 == '\n' ) s1++;
Paul Bakker40e46942009-01-03 21:51:57 +00001147 else return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001148
1149 enc = 0;
1150
1151 if( memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 )
1152 {
Paul Bakker40e46942009-01-03 21:51:57 +00001153#if defined(POLARSSL_DES_C)
Paul Bakker5121ce52009-01-03 21:22:43 +00001154 enc++;
1155
1156 s1 += 22;
1157 if( *s1 == '\r' ) s1++;
1158 if( *s1 == '\n' ) s1++;
Paul Bakker40e46942009-01-03 21:51:57 +00001159 else return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001160
1161 if( memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001162 return( POLARSSL_ERR_X509_KEY_UNKNOWN_ENC_ALG );
Paul Bakker5121ce52009-01-03 21:22:43 +00001163
1164 s1 += 23;
1165 if( x509_get_iv( s1, des3_iv ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001166 return( POLARSSL_ERR_X509_KEY_INVALID_ENC_IV );
Paul Bakker5121ce52009-01-03 21:22:43 +00001167
1168 s1 += 16;
1169 if( *s1 == '\r' ) s1++;
1170 if( *s1 == '\n' ) s1++;
Paul Bakker40e46942009-01-03 21:51:57 +00001171 else return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001172#else
Paul Bakker40e46942009-01-03 21:51:57 +00001173 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001174#endif
1175 }
1176
1177 len = 0;
1178 ret = base64_decode( NULL, &len, s1, s2 - s1 );
1179
Paul Bakker40e46942009-01-03 21:51:57 +00001180 if( ret == POLARSSL_ERR_BASE64_INVALID_CHARACTER )
1181 return( ret | POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001182
1183 if( ( buf = (unsigned char *) malloc( len ) ) == NULL )
1184 return( 1 );
1185
1186 if( ( ret = base64_decode( buf, &len, s1, s2 - s1 ) ) != 0 )
1187 {
1188 free( buf );
Paul Bakker40e46942009-01-03 21:51:57 +00001189 return( ret | POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001190 }
1191
1192 buflen = len;
1193
1194 if( enc != 0 )
1195 {
Paul Bakker40e46942009-01-03 21:51:57 +00001196#if defined(POLARSSL_DES_C)
Paul Bakker5121ce52009-01-03 21:22:43 +00001197 if( pwd == NULL )
1198 {
1199 free( buf );
Paul Bakker40e46942009-01-03 21:51:57 +00001200 return( POLARSSL_ERR_X509_KEY_PASSWORD_REQUIRED );
Paul Bakker5121ce52009-01-03 21:22:43 +00001201 }
1202
1203 x509_des3_decrypt( des3_iv, buf, buflen, pwd, pwdlen );
1204
1205 if( buf[0] != 0x30 || buf[1] != 0x82 ||
1206 buf[4] != 0x02 || buf[5] != 0x01 )
1207 {
1208 free( buf );
Paul Bakker40e46942009-01-03 21:51:57 +00001209 return( POLARSSL_ERR_X509_KEY_PASSWORD_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001210 }
1211#else
Paul Bakker40e46942009-01-03 21:51:57 +00001212 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001213#endif
1214 }
1215 }
1216
1217 memset( rsa, 0, sizeof( rsa_context ) );
1218
1219 p = buf;
1220 end = buf + buflen;
1221
1222 /*
1223 * RSAPrivateKey ::= SEQUENCE {
1224 * version Version,
1225 * modulus INTEGER, -- n
1226 * publicExponent INTEGER, -- e
1227 * privateExponent INTEGER, -- d
1228 * prime1 INTEGER, -- p
1229 * prime2 INTEGER, -- q
1230 * exponent1 INTEGER, -- d mod (p-1)
1231 * exponent2 INTEGER, -- d mod (q-1)
1232 * coefficient INTEGER, -- (inverse of q) mod p
1233 * otherPrimeInfos OtherPrimeInfos OPTIONAL
1234 * }
1235 */
1236 if( ( ret = asn1_get_tag( &p, end, &len,
1237 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1238 {
1239 if( s1 != NULL )
1240 free( buf );
1241
1242 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001243 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001244 }
1245
1246 end = p + len;
1247
1248 if( ( ret = asn1_get_int( &p, end, &rsa->ver ) ) != 0 )
1249 {
1250 if( s1 != NULL )
1251 free( buf );
1252
1253 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001254 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001255 }
1256
1257 if( rsa->ver != 0 )
1258 {
1259 if( s1 != NULL )
1260 free( buf );
1261
1262 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001263 return( ret | POLARSSL_ERR_X509_KEY_INVALID_VERSION );
Paul Bakker5121ce52009-01-03 21:22:43 +00001264 }
1265
1266 if( ( ret = asn1_get_mpi( &p, end, &rsa->N ) ) != 0 ||
1267 ( ret = asn1_get_mpi( &p, end, &rsa->E ) ) != 0 ||
1268 ( ret = asn1_get_mpi( &p, end, &rsa->D ) ) != 0 ||
1269 ( ret = asn1_get_mpi( &p, end, &rsa->P ) ) != 0 ||
1270 ( ret = asn1_get_mpi( &p, end, &rsa->Q ) ) != 0 ||
1271 ( ret = asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 ||
1272 ( ret = asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 ||
1273 ( ret = asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 )
1274 {
1275 if( s1 != NULL )
1276 free( buf );
1277
1278 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001279 return( ret | POLARSSL_ERR_X509_KEY_INVALID_FORMAT );
Paul Bakker5121ce52009-01-03 21:22:43 +00001280 }
1281
1282 rsa->len = mpi_size( &rsa->N );
1283
1284 if( p != end )
1285 {
1286 if( s1 != NULL )
1287 free( buf );
1288
1289 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001290 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT |
1291 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001292 }
1293
1294 if( ( ret = rsa_check_privkey( rsa ) ) != 0 )
1295 {
1296 if( s1 != NULL )
1297 free( buf );
1298
1299 rsa_free( rsa );
1300 return( ret );
1301 }
1302
1303 if( s1 != NULL )
1304 free( buf );
1305
1306 return( 0 );
1307}
1308
1309/*
1310 * Load and parse a private RSA key
1311 */
1312int x509parse_keyfile( rsa_context *rsa, char *path, char *pwd )
1313{
1314 int ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001315 size_t n;
1316 unsigned char *buf;
1317
Paul Bakker2b245eb2009-04-19 18:44:26 +00001318 if ( load_file( path, &buf, &n ) )
Paul Bakker5121ce52009-01-03 21:22:43 +00001319 return( 1 );
1320
Paul Bakker5121ce52009-01-03 21:22:43 +00001321 if( pwd == NULL )
1322 ret = x509parse_key( rsa, buf, (int) n, NULL, 0 );
1323 else
1324 ret = x509parse_key( rsa, buf, (int) n,
1325 (unsigned char *) pwd, strlen( pwd ) );
1326
1327 memset( buf, 0, n + 1 );
1328 free( buf );
Paul Bakker5121ce52009-01-03 21:22:43 +00001329
1330 return( ret );
1331}
1332
1333#if defined _MSC_VER && !defined snprintf
1334#define snprintf _snprintf
1335#endif
1336
1337/*
1338 * Store the name in printable form into buf; no more
1339 * than (end - buf) characters will be written
1340 */
1341int x509parse_dn_gets( char *buf, char *end, x509_name *dn )
1342{
1343 int i;
1344 unsigned char c;
1345 x509_name *name;
1346 char s[128], *p;
1347
1348 memset( s, 0, sizeof( s ) );
1349
1350 name = dn;
1351 p = buf;
1352
1353 while( name != NULL )
1354 {
1355 if( name != dn )
1356 p += snprintf( p, end - p, ", " );
1357
1358 if( memcmp( name->oid.p, OID_X520, 2 ) == 0 )
1359 {
1360 switch( name->oid.p[2] )
1361 {
1362 case X520_COMMON_NAME:
1363 p += snprintf( p, end - p, "CN=" ); break;
1364
1365 case X520_COUNTRY:
1366 p += snprintf( p, end - p, "C=" ); break;
1367
1368 case X520_LOCALITY:
1369 p += snprintf( p, end - p, "L=" ); break;
1370
1371 case X520_STATE:
1372 p += snprintf( p, end - p, "ST=" ); break;
1373
1374 case X520_ORGANIZATION:
1375 p += snprintf( p, end - p, "O=" ); break;
1376
1377 case X520_ORG_UNIT:
1378 p += snprintf( p, end - p, "OU=" ); break;
1379
1380 default:
1381 p += snprintf( p, end - p, "0x%02X=",
1382 name->oid.p[2] );
1383 break;
1384 }
1385 }
1386 else if( memcmp( name->oid.p, OID_PKCS9, 8 ) == 0 )
1387 {
1388 switch( name->oid.p[8] )
1389 {
1390 case PKCS9_EMAIL:
1391 p += snprintf( p, end - p, "emailAddress=" ); break;
1392
1393 default:
1394 p += snprintf( p, end - p, "0x%02X=",
1395 name->oid.p[8] );
1396 break;
1397 }
1398 }
1399 else
1400 p += snprintf( p, end - p, "\?\?=" );
1401
1402 for( i = 0; i < name->val.len; i++ )
1403 {
1404 if( i >= (int) sizeof( s ) - 1 )
1405 break;
1406
1407 c = name->val.p[i];
1408 if( c < 32 || c == 127 || ( c > 128 && c < 160 ) )
1409 s[i] = '?';
1410 else s[i] = c;
1411 }
1412 s[i] = '\0';
1413 p += snprintf( p, end - p, "%s", s );
1414 name = name->next;
1415 }
1416
1417 return( p - buf );
1418}
1419
1420/*
1421 * Return an informational string about the
1422 * certificate, or NULL if memory allocation failed
1423 */
1424char *x509parse_cert_info( char *prefix, x509_cert *crt )
1425{
1426 int i, n;
1427 char *p, *end;
Paul Bakker3681b112009-02-07 17:14:21 +00001428 static char buf[1024];
Paul Bakker5121ce52009-01-03 21:22:43 +00001429
1430 p = buf;
1431 end = buf + sizeof( buf ) - 1;
1432
1433 p += snprintf( p, end - p, "%scert. version : %d\n",
1434 prefix, crt->version );
1435 p += snprintf( p, end - p, "%sserial number : ",
1436 prefix );
1437
1438 n = ( crt->serial.len <= 32 )
1439 ? crt->serial.len : 32;
1440
1441 for( i = 0; i < n; i++ )
1442 p += snprintf( p, end - p, "%02X%s",
1443 crt->serial.p[i], ( i < n - 1 ) ? ":" : "" );
1444
1445 p += snprintf( p, end - p, "\n%sissuer name : ", prefix );
1446 p += x509parse_dn_gets( p, end, &crt->issuer );
1447
1448 p += snprintf( p, end - p, "\n%ssubject name : ", prefix );
1449 p += x509parse_dn_gets( p, end, &crt->subject );
1450
1451 p += snprintf( p, end - p, "\n%sissued on : " \
1452 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
1453 crt->valid_from.year, crt->valid_from.mon,
1454 crt->valid_from.day, crt->valid_from.hour,
1455 crt->valid_from.min, crt->valid_from.sec );
1456
1457 p += snprintf( p, end - p, "\n%sexpires on : " \
1458 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
1459 crt->valid_to.year, crt->valid_to.mon,
1460 crt->valid_to.day, crt->valid_to.hour,
1461 crt->valid_to.min, crt->valid_to.sec );
1462
1463 p += snprintf( p, end - p, "\n%ssigned using : RSA+", prefix );
1464
1465 switch( crt->sig_oid1.p[8] )
1466 {
Paul Bakker4593aea2009-02-09 22:32:35 +00001467 case SIG_RSA_MD2 : p += snprintf( p, end - p, "MD2" ); break;
1468 case SIG_RSA_MD4 : p += snprintf( p, end - p, "MD4" ); break;
1469 case SIG_RSA_MD5 : p += snprintf( p, end - p, "MD5" ); break;
1470 case SIG_RSA_SHA1 : p += snprintf( p, end - p, "SHA1" ); break;
1471 case SIG_RSA_SHA224 : p += snprintf( p, end - p, "SHA224" ); break;
1472 case SIG_RSA_SHA256 : p += snprintf( p, end - p, "SHA256" ); break;
1473 case SIG_RSA_SHA384 : p += snprintf( p, end - p, "SHA384" ); break;
1474 case SIG_RSA_SHA512 : p += snprintf( p, end - p, "SHA512" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00001475 default: p += snprintf( p, end - p, "???" ); break;
1476 }
1477
1478 p += snprintf( p, end - p, "\n%sRSA key size : %d bits\n", prefix,
1479 crt->rsa.N.n * (int) sizeof( unsigned long ) * 8 );
1480
1481 return( buf );
1482}
1483
1484/*
1485 * Return 0 if the certificate is still valid, or BADCERT_EXPIRED
1486 */
1487int x509parse_expired( x509_cert *crt )
1488{
1489 struct tm *lt;
1490 time_t tt;
1491
1492 tt = time( NULL );
1493 lt = localtime( &tt );
1494
1495 if( lt->tm_year > crt->valid_to.year - 1900 )
1496 return( BADCERT_EXPIRED );
1497
1498 if( lt->tm_year == crt->valid_to.year - 1900 &&
1499 lt->tm_mon > crt->valid_to.mon - 1 )
1500 return( BADCERT_EXPIRED );
1501
1502 if( lt->tm_year == crt->valid_to.year - 1900 &&
1503 lt->tm_mon == crt->valid_to.mon - 1 &&
1504 lt->tm_mday > crt->valid_to.day )
1505 return( BADCERT_EXPIRED );
1506
1507 return( 0 );
1508}
1509
1510static void x509_hash( unsigned char *in, int len, int alg,
1511 unsigned char *out )
1512{
1513 switch( alg )
1514 {
Paul Bakker40e46942009-01-03 21:51:57 +00001515#if defined(POLARSSL_MD2_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00001516 case SIG_RSA_MD2 : md2( in, len, out ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00001517#endif
Paul Bakker40e46942009-01-03 21:51:57 +00001518#if defined(POLARSSL_MD4_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00001519 case SIG_RSA_MD4 : md4( in, len, out ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00001520#endif
Paul Bakker4593aea2009-02-09 22:32:35 +00001521 case SIG_RSA_MD5 : md5( in, len, out ); break;
1522 case SIG_RSA_SHA1 : sha1( in, len, out ); break;
1523#if defined(POLARSSL_SHA2_C)
1524 case SIG_RSA_SHA224 : sha2( in, len, out, 1 ); break;
1525 case SIG_RSA_SHA256 : sha2( in, len, out, 0 ); break;
1526#endif
1527#if defined(POLARSSL_SHA2_C)
1528 case SIG_RSA_SHA384 : sha4( in, len, out, 1 ); break;
1529 case SIG_RSA_SHA512 : sha4( in, len, out, 0 ); break;
1530#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00001531 default:
1532 memset( out, '\xFF', len );
1533 break;
1534 }
1535}
1536
1537/*
1538 * Verify the certificate validity
1539 */
1540int x509parse_verify( x509_cert *crt,
1541 x509_cert *trust_ca,
1542 char *cn, int *flags )
1543{
1544 int cn_len;
1545 int hash_id;
1546 int pathlen;
1547 x509_cert *cur;
1548 x509_name *name;
Paul Bakker4593aea2009-02-09 22:32:35 +00001549 unsigned char hash[64];
Paul Bakker5121ce52009-01-03 21:22:43 +00001550
1551 *flags = x509parse_expired( crt );
1552
1553 if( cn != NULL )
1554 {
1555 name = &crt->subject;
1556 cn_len = strlen( cn );
1557
1558 while( name != NULL )
1559 {
1560 if( memcmp( name->oid.p, OID_CN, 3 ) == 0 &&
1561 memcmp( name->val.p, cn, cn_len ) == 0 &&
1562 name->val.len == cn_len )
1563 break;
1564
1565 name = name->next;
1566 }
1567
1568 if( name == NULL )
1569 *flags |= BADCERT_CN_MISMATCH;
1570 }
1571
1572 *flags |= BADCERT_NOT_TRUSTED;
1573
1574 /*
1575 * Iterate upwards in the given cert chain,
1576 * ignoring any upper cert with CA != TRUE.
1577 */
1578 cur = crt->next;
1579
1580 pathlen = 1;
1581
Paul Bakker7c6d4a42009-03-28 20:35:47 +00001582 while( cur != NULL && cur->version != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001583 {
1584 if( cur->ca_istrue == 0 ||
1585 crt->issuer_raw.len != cur->subject_raw.len ||
1586 memcmp( crt->issuer_raw.p, cur->subject_raw.p,
1587 crt->issuer_raw.len ) != 0 )
1588 {
1589 cur = cur->next;
1590 continue;
1591 }
1592
1593 hash_id = crt->sig_oid1.p[8];
1594
1595 x509_hash( crt->tbs.p, crt->tbs.len, hash_id, hash );
1596
1597 if( rsa_pkcs1_verify( &cur->rsa, RSA_PUBLIC, hash_id,
1598 0, hash, crt->sig.p ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001599 return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +00001600
1601 pathlen++;
1602
1603 crt = cur;
1604 cur = crt->next;
1605 }
1606
1607 /*
1608 * Atempt to validate topmost cert with our CA chain.
1609 */
Paul Bakker7c6d4a42009-03-28 20:35:47 +00001610 while( trust_ca != NULL && trust_ca->version != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001611 {
1612 if( crt->issuer_raw.len != trust_ca->subject_raw.len ||
1613 memcmp( crt->issuer_raw.p, trust_ca->subject_raw.p,
1614 crt->issuer_raw.len ) != 0 )
1615 {
1616 trust_ca = trust_ca->next;
1617 continue;
1618 }
1619
1620 if( trust_ca->max_pathlen > 0 &&
1621 trust_ca->max_pathlen < pathlen )
1622 break;
1623
1624 hash_id = crt->sig_oid1.p[8];
1625
1626 x509_hash( crt->tbs.p, crt->tbs.len, hash_id, hash );
1627
1628 if( rsa_pkcs1_verify( &trust_ca->rsa, RSA_PUBLIC, hash_id,
1629 0, hash, crt->sig.p ) == 0 )
1630 {
1631 /*
1632 * cert. is signed by a trusted CA
1633 */
1634 *flags &= ~BADCERT_NOT_TRUSTED;
1635 break;
1636 }
1637
1638 trust_ca = trust_ca->next;
1639 }
1640
1641 if( *flags != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001642 return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +00001643
1644 return( 0 );
1645}
1646
1647/*
1648 * Unallocate all certificate data
1649 */
1650void x509_free( x509_cert *crt )
1651{
1652 x509_cert *cert_cur = crt;
1653 x509_cert *cert_prv;
1654 x509_name *name_cur;
1655 x509_name *name_prv;
1656
1657 if( crt == NULL )
1658 return;
1659
1660 do
1661 {
1662 rsa_free( &cert_cur->rsa );
1663
1664 name_cur = cert_cur->issuer.next;
1665 while( name_cur != NULL )
1666 {
1667 name_prv = name_cur;
1668 name_cur = name_cur->next;
1669 memset( name_prv, 0, sizeof( x509_name ) );
1670 free( name_prv );
1671 }
1672
1673 name_cur = cert_cur->subject.next;
1674 while( name_cur != NULL )
1675 {
1676 name_prv = name_cur;
1677 name_cur = name_cur->next;
1678 memset( name_prv, 0, sizeof( x509_name ) );
1679 free( name_prv );
1680 }
1681
1682 if( cert_cur->raw.p != NULL )
1683 {
1684 memset( cert_cur->raw.p, 0, cert_cur->raw.len );
1685 free( cert_cur->raw.p );
1686 }
1687
1688 cert_cur = cert_cur->next;
1689 }
1690 while( cert_cur != NULL );
1691
1692 cert_cur = crt;
1693 do
1694 {
1695 cert_prv = cert_cur;
1696 cert_cur = cert_cur->next;
1697
1698 memset( cert_prv, 0, sizeof( x509_cert ) );
1699 if( cert_prv != crt )
1700 free( cert_prv );
1701 }
1702 while( cert_cur != NULL );
1703}
1704
Paul Bakker40e46942009-01-03 21:51:57 +00001705#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00001706
Paul Bakker40e46942009-01-03 21:51:57 +00001707#include "polarssl/certs.h"
Paul Bakker5121ce52009-01-03 21:22:43 +00001708
1709/*
1710 * Checkup routine
1711 */
1712int x509_self_test( int verbose )
1713{
1714 int ret, i, j;
1715 x509_cert cacert;
1716 x509_cert clicert;
1717 rsa_context rsa;
1718
1719 if( verbose != 0 )
1720 printf( " X.509 certificate load: " );
1721
1722 memset( &clicert, 0, sizeof( x509_cert ) );
1723
1724 ret = x509parse_crt( &clicert, (unsigned char *) test_cli_crt,
1725 strlen( test_cli_crt ) );
1726 if( ret != 0 )
1727 {
1728 if( verbose != 0 )
1729 printf( "failed\n" );
1730
1731 return( ret );
1732 }
1733
1734 memset( &cacert, 0, sizeof( x509_cert ) );
1735
1736 ret = x509parse_crt( &cacert, (unsigned char *) test_ca_crt,
1737 strlen( test_ca_crt ) );
1738 if( ret != 0 )
1739 {
1740 if( verbose != 0 )
1741 printf( "failed\n" );
1742
1743 return( ret );
1744 }
1745
1746 if( verbose != 0 )
1747 printf( "passed\n X.509 private key load: " );
1748
1749 i = strlen( test_ca_key );
1750 j = strlen( test_ca_pwd );
1751
1752 if( ( ret = x509parse_key( &rsa,
1753 (unsigned char *) test_ca_key, i,
1754 (unsigned char *) test_ca_pwd, j ) ) != 0 )
1755 {
1756 if( verbose != 0 )
1757 printf( "failed\n" );
1758
1759 return( ret );
1760 }
1761
1762 if( verbose != 0 )
1763 printf( "passed\n X.509 signature verify: ");
1764
1765 ret = x509parse_verify( &clicert, &cacert, "Joe User", &i );
1766 if( ret != 0 )
1767 {
1768 if( verbose != 0 )
1769 printf( "failed\n" );
1770
1771 return( ret );
1772 }
1773
1774 if( verbose != 0 )
1775 printf( "passed\n\n" );
1776
1777 x509_free( &cacert );
1778 x509_free( &clicert );
1779 rsa_free( &rsa );
1780
1781 return( 0 );
1782}
1783
1784#endif
1785
1786#endif