blob: 7d88a0cc31dae41b48584c6bdbf713a2e1ab6552 [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/*
1007 * Load one or more certificates and add them to the chained list
1008 */
1009int x509parse_crtfile( x509_cert *chain, char *path )
1010{
1011 int ret;
1012 FILE *f;
1013 size_t n;
1014 unsigned char *buf;
1015
1016 if( ( f = fopen( path, "rb" ) ) == NULL )
1017 return( 1 );
1018
1019 fseek( f, 0, SEEK_END );
1020 n = (size_t) ftell( f );
1021 fseek( f, 0, SEEK_SET );
1022
1023 if( ( buf = (unsigned char *) malloc( n + 1 ) ) == NULL )
1024 return( 1 );
1025
1026 if( fread( buf, 1, n, f ) != n )
1027 {
1028 fclose( f );
1029 free( buf );
1030 return( 1 );
1031 }
1032
1033 buf[n] = '\0';
1034
1035 ret = x509parse_crt( chain, buf, (int) n );
1036
1037 memset( buf, 0, n + 1 );
1038 free( buf );
1039 fclose( f );
1040
1041 return( ret );
1042}
1043
Paul Bakker40e46942009-01-03 21:51:57 +00001044#if defined(POLARSSL_DES_C)
Paul Bakker5121ce52009-01-03 21:22:43 +00001045/*
1046 * Read a 16-byte hex string and convert it to binary
1047 */
1048static int x509_get_iv( unsigned char *s, unsigned char iv[8] )
1049{
1050 int i, j, k;
1051
1052 memset( iv, 0, 8 );
1053
1054 for( i = 0; i < 16; i++, s++ )
1055 {
1056 if( *s >= '0' && *s <= '9' ) j = *s - '0'; else
1057 if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else
1058 if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else
Paul Bakker40e46942009-01-03 21:51:57 +00001059 return( POLARSSL_ERR_X509_KEY_INVALID_ENC_IV );
Paul Bakker5121ce52009-01-03 21:22:43 +00001060
1061 k = ( ( i & 1 ) != 0 ) ? j : j << 4;
1062
1063 iv[i >> 1] = (unsigned char)( iv[i >> 1] | k );
1064 }
1065
1066 return( 0 );
1067}
1068
1069/*
1070 * Decrypt with 3DES-CBC, using PBKDF1 for key derivation
1071 */
1072static void x509_des3_decrypt( unsigned char des3_iv[8],
1073 unsigned char *buf, int buflen,
1074 unsigned char *pwd, int pwdlen )
1075{
1076 md5_context md5_ctx;
1077 des3_context des3_ctx;
1078 unsigned char md5sum[16];
1079 unsigned char des3_key[24];
1080
1081 /*
1082 * 3DES key[ 0..15] = MD5(pwd || IV)
1083 * key[16..23] = MD5(pwd || IV || 3DES key[ 0..15])
1084 */
1085 md5_starts( &md5_ctx );
1086 md5_update( &md5_ctx, pwd, pwdlen );
1087 md5_update( &md5_ctx, des3_iv, 8 );
1088 md5_finish( &md5_ctx, md5sum );
1089 memcpy( des3_key, md5sum, 16 );
1090
1091 md5_starts( &md5_ctx );
1092 md5_update( &md5_ctx, md5sum, 16 );
1093 md5_update( &md5_ctx, pwd, pwdlen );
1094 md5_update( &md5_ctx, des3_iv, 8 );
1095 md5_finish( &md5_ctx, md5sum );
1096 memcpy( des3_key + 16, md5sum, 8 );
1097
1098 des3_set3key_dec( &des3_ctx, des3_key );
1099 des3_crypt_cbc( &des3_ctx, DES_DECRYPT, buflen,
1100 des3_iv, buf, buf );
1101
1102 memset( &md5_ctx, 0, sizeof( md5_ctx ) );
1103 memset( &des3_ctx, 0, sizeof( des3_ctx ) );
1104 memset( md5sum, 0, 16 );
1105 memset( des3_key, 0, 24 );
1106}
1107#endif
1108
1109/*
1110 * Parse a private RSA key
1111 */
1112int x509parse_key( rsa_context *rsa, unsigned char *buf, int buflen,
1113 unsigned char *pwd, int pwdlen )
1114{
1115 int ret, len, enc;
1116 unsigned char *s1, *s2;
1117 unsigned char *p, *end;
1118 unsigned char des3_iv[8];
1119
1120 s1 = (unsigned char *) strstr( (char *) buf,
1121 "-----BEGIN RSA PRIVATE KEY-----" );
1122
1123 if( s1 != NULL )
1124 {
1125 s2 = (unsigned char *) strstr( (char *) buf,
1126 "-----END RSA PRIVATE KEY-----" );
1127
1128 if( s2 == NULL || s2 <= s1 )
Paul Bakker40e46942009-01-03 21:51:57 +00001129 return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001130
1131 s1 += 31;
1132 if( *s1 == '\r' ) s1++;
1133 if( *s1 == '\n' ) s1++;
Paul Bakker40e46942009-01-03 21:51:57 +00001134 else return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001135
1136 enc = 0;
1137
1138 if( memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 )
1139 {
Paul Bakker40e46942009-01-03 21:51:57 +00001140#if defined(POLARSSL_DES_C)
Paul Bakker5121ce52009-01-03 21:22:43 +00001141 enc++;
1142
1143 s1 += 22;
1144 if( *s1 == '\r' ) s1++;
1145 if( *s1 == '\n' ) s1++;
Paul Bakker40e46942009-01-03 21:51:57 +00001146 else return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001147
1148 if( memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001149 return( POLARSSL_ERR_X509_KEY_UNKNOWN_ENC_ALG );
Paul Bakker5121ce52009-01-03 21:22:43 +00001150
1151 s1 += 23;
1152 if( x509_get_iv( s1, des3_iv ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001153 return( POLARSSL_ERR_X509_KEY_INVALID_ENC_IV );
Paul Bakker5121ce52009-01-03 21:22:43 +00001154
1155 s1 += 16;
1156 if( *s1 == '\r' ) s1++;
1157 if( *s1 == '\n' ) s1++;
Paul Bakker40e46942009-01-03 21:51:57 +00001158 else return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001159#else
Paul Bakker40e46942009-01-03 21:51:57 +00001160 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001161#endif
1162 }
1163
1164 len = 0;
1165 ret = base64_decode( NULL, &len, s1, s2 - s1 );
1166
Paul Bakker40e46942009-01-03 21:51:57 +00001167 if( ret == POLARSSL_ERR_BASE64_INVALID_CHARACTER )
1168 return( ret | POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001169
1170 if( ( buf = (unsigned char *) malloc( len ) ) == NULL )
1171 return( 1 );
1172
1173 if( ( ret = base64_decode( buf, &len, s1, s2 - s1 ) ) != 0 )
1174 {
1175 free( buf );
Paul Bakker40e46942009-01-03 21:51:57 +00001176 return( ret | POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001177 }
1178
1179 buflen = len;
1180
1181 if( enc != 0 )
1182 {
Paul Bakker40e46942009-01-03 21:51:57 +00001183#if defined(POLARSSL_DES_C)
Paul Bakker5121ce52009-01-03 21:22:43 +00001184 if( pwd == NULL )
1185 {
1186 free( buf );
Paul Bakker40e46942009-01-03 21:51:57 +00001187 return( POLARSSL_ERR_X509_KEY_PASSWORD_REQUIRED );
Paul Bakker5121ce52009-01-03 21:22:43 +00001188 }
1189
1190 x509_des3_decrypt( des3_iv, buf, buflen, pwd, pwdlen );
1191
1192 if( buf[0] != 0x30 || buf[1] != 0x82 ||
1193 buf[4] != 0x02 || buf[5] != 0x01 )
1194 {
1195 free( buf );
Paul Bakker40e46942009-01-03 21:51:57 +00001196 return( POLARSSL_ERR_X509_KEY_PASSWORD_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001197 }
1198#else
Paul Bakker40e46942009-01-03 21:51:57 +00001199 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001200#endif
1201 }
1202 }
1203
1204 memset( rsa, 0, sizeof( rsa_context ) );
1205
1206 p = buf;
1207 end = buf + buflen;
1208
1209 /*
1210 * RSAPrivateKey ::= SEQUENCE {
1211 * version Version,
1212 * modulus INTEGER, -- n
1213 * publicExponent INTEGER, -- e
1214 * privateExponent INTEGER, -- d
1215 * prime1 INTEGER, -- p
1216 * prime2 INTEGER, -- q
1217 * exponent1 INTEGER, -- d mod (p-1)
1218 * exponent2 INTEGER, -- d mod (q-1)
1219 * coefficient INTEGER, -- (inverse of q) mod p
1220 * otherPrimeInfos OtherPrimeInfos OPTIONAL
1221 * }
1222 */
1223 if( ( ret = asn1_get_tag( &p, end, &len,
1224 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1225 {
1226 if( s1 != NULL )
1227 free( buf );
1228
1229 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001230 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001231 }
1232
1233 end = p + len;
1234
1235 if( ( ret = asn1_get_int( &p, end, &rsa->ver ) ) != 0 )
1236 {
1237 if( s1 != NULL )
1238 free( buf );
1239
1240 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001241 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001242 }
1243
1244 if( rsa->ver != 0 )
1245 {
1246 if( s1 != NULL )
1247 free( buf );
1248
1249 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001250 return( ret | POLARSSL_ERR_X509_KEY_INVALID_VERSION );
Paul Bakker5121ce52009-01-03 21:22:43 +00001251 }
1252
1253 if( ( ret = asn1_get_mpi( &p, end, &rsa->N ) ) != 0 ||
1254 ( ret = asn1_get_mpi( &p, end, &rsa->E ) ) != 0 ||
1255 ( ret = asn1_get_mpi( &p, end, &rsa->D ) ) != 0 ||
1256 ( ret = asn1_get_mpi( &p, end, &rsa->P ) ) != 0 ||
1257 ( ret = asn1_get_mpi( &p, end, &rsa->Q ) ) != 0 ||
1258 ( ret = asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 ||
1259 ( ret = asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 ||
1260 ( ret = asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 )
1261 {
1262 if( s1 != NULL )
1263 free( buf );
1264
1265 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001266 return( ret | POLARSSL_ERR_X509_KEY_INVALID_FORMAT );
Paul Bakker5121ce52009-01-03 21:22:43 +00001267 }
1268
1269 rsa->len = mpi_size( &rsa->N );
1270
1271 if( p != end )
1272 {
1273 if( s1 != NULL )
1274 free( buf );
1275
1276 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001277 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT |
1278 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001279 }
1280
1281 if( ( ret = rsa_check_privkey( rsa ) ) != 0 )
1282 {
1283 if( s1 != NULL )
1284 free( buf );
1285
1286 rsa_free( rsa );
1287 return( ret );
1288 }
1289
1290 if( s1 != NULL )
1291 free( buf );
1292
1293 return( 0 );
1294}
1295
1296/*
1297 * Load and parse a private RSA key
1298 */
1299int x509parse_keyfile( rsa_context *rsa, char *path, char *pwd )
1300{
1301 int ret;
1302 FILE *f;
1303 size_t n;
1304 unsigned char *buf;
1305
1306 if( ( f = fopen( path, "rb" ) ) == NULL )
1307 return( 1 );
1308
1309 fseek( f, 0, SEEK_END );
1310 n = (size_t) ftell( f );
1311 fseek( f, 0, SEEK_SET );
1312
1313 if( ( buf = (unsigned char *) malloc( n + 1 ) ) == NULL )
1314 return( 1 );
1315
1316 if( fread( buf, 1, n, f ) != n )
1317 {
1318 fclose( f );
1319 free( buf );
1320 return( 1 );
1321 }
1322
1323 buf[n] = '\0';
1324
1325 if( pwd == NULL )
1326 ret = x509parse_key( rsa, buf, (int) n, NULL, 0 );
1327 else
1328 ret = x509parse_key( rsa, buf, (int) n,
1329 (unsigned char *) pwd, strlen( pwd ) );
1330
1331 memset( buf, 0, n + 1 );
1332 free( buf );
1333 fclose( f );
1334
1335 return( ret );
1336}
1337
1338#if defined _MSC_VER && !defined snprintf
1339#define snprintf _snprintf
1340#endif
1341
1342/*
1343 * Store the name in printable form into buf; no more
1344 * than (end - buf) characters will be written
1345 */
1346int x509parse_dn_gets( char *buf, char *end, x509_name *dn )
1347{
1348 int i;
1349 unsigned char c;
1350 x509_name *name;
1351 char s[128], *p;
1352
1353 memset( s, 0, sizeof( s ) );
1354
1355 name = dn;
1356 p = buf;
1357
1358 while( name != NULL )
1359 {
1360 if( name != dn )
1361 p += snprintf( p, end - p, ", " );
1362
1363 if( memcmp( name->oid.p, OID_X520, 2 ) == 0 )
1364 {
1365 switch( name->oid.p[2] )
1366 {
1367 case X520_COMMON_NAME:
1368 p += snprintf( p, end - p, "CN=" ); break;
1369
1370 case X520_COUNTRY:
1371 p += snprintf( p, end - p, "C=" ); break;
1372
1373 case X520_LOCALITY:
1374 p += snprintf( p, end - p, "L=" ); break;
1375
1376 case X520_STATE:
1377 p += snprintf( p, end - p, "ST=" ); break;
1378
1379 case X520_ORGANIZATION:
1380 p += snprintf( p, end - p, "O=" ); break;
1381
1382 case X520_ORG_UNIT:
1383 p += snprintf( p, end - p, "OU=" ); break;
1384
1385 default:
1386 p += snprintf( p, end - p, "0x%02X=",
1387 name->oid.p[2] );
1388 break;
1389 }
1390 }
1391 else if( memcmp( name->oid.p, OID_PKCS9, 8 ) == 0 )
1392 {
1393 switch( name->oid.p[8] )
1394 {
1395 case PKCS9_EMAIL:
1396 p += snprintf( p, end - p, "emailAddress=" ); break;
1397
1398 default:
1399 p += snprintf( p, end - p, "0x%02X=",
1400 name->oid.p[8] );
1401 break;
1402 }
1403 }
1404 else
1405 p += snprintf( p, end - p, "\?\?=" );
1406
1407 for( i = 0; i < name->val.len; i++ )
1408 {
1409 if( i >= (int) sizeof( s ) - 1 )
1410 break;
1411
1412 c = name->val.p[i];
1413 if( c < 32 || c == 127 || ( c > 128 && c < 160 ) )
1414 s[i] = '?';
1415 else s[i] = c;
1416 }
1417 s[i] = '\0';
1418 p += snprintf( p, end - p, "%s", s );
1419 name = name->next;
1420 }
1421
1422 return( p - buf );
1423}
1424
1425/*
1426 * Return an informational string about the
1427 * certificate, or NULL if memory allocation failed
1428 */
1429char *x509parse_cert_info( char *prefix, x509_cert *crt )
1430{
1431 int i, n;
1432 char *p, *end;
Paul Bakker3681b112009-02-07 17:14:21 +00001433 static char buf[1024];
Paul Bakker5121ce52009-01-03 21:22:43 +00001434
1435 p = buf;
1436 end = buf + sizeof( buf ) - 1;
1437
1438 p += snprintf( p, end - p, "%scert. version : %d\n",
1439 prefix, crt->version );
1440 p += snprintf( p, end - p, "%sserial number : ",
1441 prefix );
1442
1443 n = ( crt->serial.len <= 32 )
1444 ? crt->serial.len : 32;
1445
1446 for( i = 0; i < n; i++ )
1447 p += snprintf( p, end - p, "%02X%s",
1448 crt->serial.p[i], ( i < n - 1 ) ? ":" : "" );
1449
1450 p += snprintf( p, end - p, "\n%sissuer name : ", prefix );
1451 p += x509parse_dn_gets( p, end, &crt->issuer );
1452
1453 p += snprintf( p, end - p, "\n%ssubject name : ", prefix );
1454 p += x509parse_dn_gets( p, end, &crt->subject );
1455
1456 p += snprintf( p, end - p, "\n%sissued on : " \
1457 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
1458 crt->valid_from.year, crt->valid_from.mon,
1459 crt->valid_from.day, crt->valid_from.hour,
1460 crt->valid_from.min, crt->valid_from.sec );
1461
1462 p += snprintf( p, end - p, "\n%sexpires on : " \
1463 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
1464 crt->valid_to.year, crt->valid_to.mon,
1465 crt->valid_to.day, crt->valid_to.hour,
1466 crt->valid_to.min, crt->valid_to.sec );
1467
1468 p += snprintf( p, end - p, "\n%ssigned using : RSA+", prefix );
1469
1470 switch( crt->sig_oid1.p[8] )
1471 {
Paul Bakker4593aea2009-02-09 22:32:35 +00001472 case SIG_RSA_MD2 : p += snprintf( p, end - p, "MD2" ); break;
1473 case SIG_RSA_MD4 : p += snprintf( p, end - p, "MD4" ); break;
1474 case SIG_RSA_MD5 : p += snprintf( p, end - p, "MD5" ); break;
1475 case SIG_RSA_SHA1 : p += snprintf( p, end - p, "SHA1" ); break;
1476 case SIG_RSA_SHA224 : p += snprintf( p, end - p, "SHA224" ); break;
1477 case SIG_RSA_SHA256 : p += snprintf( p, end - p, "SHA256" ); break;
1478 case SIG_RSA_SHA384 : p += snprintf( p, end - p, "SHA384" ); break;
1479 case SIG_RSA_SHA512 : p += snprintf( p, end - p, "SHA512" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00001480 default: p += snprintf( p, end - p, "???" ); break;
1481 }
1482
1483 p += snprintf( p, end - p, "\n%sRSA key size : %d bits\n", prefix,
1484 crt->rsa.N.n * (int) sizeof( unsigned long ) * 8 );
1485
1486 return( buf );
1487}
1488
1489/*
1490 * Return 0 if the certificate is still valid, or BADCERT_EXPIRED
1491 */
1492int x509parse_expired( x509_cert *crt )
1493{
1494 struct tm *lt;
1495 time_t tt;
1496
1497 tt = time( NULL );
1498 lt = localtime( &tt );
1499
1500 if( lt->tm_year > crt->valid_to.year - 1900 )
1501 return( BADCERT_EXPIRED );
1502
1503 if( lt->tm_year == crt->valid_to.year - 1900 &&
1504 lt->tm_mon > crt->valid_to.mon - 1 )
1505 return( BADCERT_EXPIRED );
1506
1507 if( lt->tm_year == crt->valid_to.year - 1900 &&
1508 lt->tm_mon == crt->valid_to.mon - 1 &&
1509 lt->tm_mday > crt->valid_to.day )
1510 return( BADCERT_EXPIRED );
1511
1512 return( 0 );
1513}
1514
1515static void x509_hash( unsigned char *in, int len, int alg,
1516 unsigned char *out )
1517{
1518 switch( alg )
1519 {
Paul Bakker40e46942009-01-03 21:51:57 +00001520#if defined(POLARSSL_MD2_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00001521 case SIG_RSA_MD2 : md2( in, len, out ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00001522#endif
Paul Bakker40e46942009-01-03 21:51:57 +00001523#if defined(POLARSSL_MD4_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00001524 case SIG_RSA_MD4 : md4( in, len, out ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00001525#endif
Paul Bakker4593aea2009-02-09 22:32:35 +00001526 case SIG_RSA_MD5 : md5( in, len, out ); break;
1527 case SIG_RSA_SHA1 : sha1( in, len, out ); break;
1528#if defined(POLARSSL_SHA2_C)
1529 case SIG_RSA_SHA224 : sha2( in, len, out, 1 ); break;
1530 case SIG_RSA_SHA256 : sha2( in, len, out, 0 ); break;
1531#endif
1532#if defined(POLARSSL_SHA2_C)
1533 case SIG_RSA_SHA384 : sha4( in, len, out, 1 ); break;
1534 case SIG_RSA_SHA512 : sha4( in, len, out, 0 ); break;
1535#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00001536 default:
1537 memset( out, '\xFF', len );
1538 break;
1539 }
1540}
1541
1542/*
1543 * Verify the certificate validity
1544 */
1545int x509parse_verify( x509_cert *crt,
1546 x509_cert *trust_ca,
1547 char *cn, int *flags )
1548{
1549 int cn_len;
1550 int hash_id;
1551 int pathlen;
1552 x509_cert *cur;
1553 x509_name *name;
Paul Bakker4593aea2009-02-09 22:32:35 +00001554 unsigned char hash[64];
Paul Bakker5121ce52009-01-03 21:22:43 +00001555
1556 *flags = x509parse_expired( crt );
1557
1558 if( cn != NULL )
1559 {
1560 name = &crt->subject;
1561 cn_len = strlen( cn );
1562
1563 while( name != NULL )
1564 {
1565 if( memcmp( name->oid.p, OID_CN, 3 ) == 0 &&
1566 memcmp( name->val.p, cn, cn_len ) == 0 &&
1567 name->val.len == cn_len )
1568 break;
1569
1570 name = name->next;
1571 }
1572
1573 if( name == NULL )
1574 *flags |= BADCERT_CN_MISMATCH;
1575 }
1576
1577 *flags |= BADCERT_NOT_TRUSTED;
1578
1579 /*
1580 * Iterate upwards in the given cert chain,
1581 * ignoring any upper cert with CA != TRUE.
1582 */
1583 cur = crt->next;
1584
1585 pathlen = 1;
1586
Paul Bakker7c6d4a42009-03-28 20:35:47 +00001587 while( cur != NULL && cur->version != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001588 {
1589 if( cur->ca_istrue == 0 ||
1590 crt->issuer_raw.len != cur->subject_raw.len ||
1591 memcmp( crt->issuer_raw.p, cur->subject_raw.p,
1592 crt->issuer_raw.len ) != 0 )
1593 {
1594 cur = cur->next;
1595 continue;
1596 }
1597
1598 hash_id = crt->sig_oid1.p[8];
1599
1600 x509_hash( crt->tbs.p, crt->tbs.len, hash_id, hash );
1601
1602 if( rsa_pkcs1_verify( &cur->rsa, RSA_PUBLIC, hash_id,
1603 0, hash, crt->sig.p ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001604 return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +00001605
1606 pathlen++;
1607
1608 crt = cur;
1609 cur = crt->next;
1610 }
1611
1612 /*
1613 * Atempt to validate topmost cert with our CA chain.
1614 */
Paul Bakker7c6d4a42009-03-28 20:35:47 +00001615 while( trust_ca != NULL && trust_ca->version != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001616 {
1617 if( crt->issuer_raw.len != trust_ca->subject_raw.len ||
1618 memcmp( crt->issuer_raw.p, trust_ca->subject_raw.p,
1619 crt->issuer_raw.len ) != 0 )
1620 {
1621 trust_ca = trust_ca->next;
1622 continue;
1623 }
1624
1625 if( trust_ca->max_pathlen > 0 &&
1626 trust_ca->max_pathlen < pathlen )
1627 break;
1628
1629 hash_id = crt->sig_oid1.p[8];
1630
1631 x509_hash( crt->tbs.p, crt->tbs.len, hash_id, hash );
1632
1633 if( rsa_pkcs1_verify( &trust_ca->rsa, RSA_PUBLIC, hash_id,
1634 0, hash, crt->sig.p ) == 0 )
1635 {
1636 /*
1637 * cert. is signed by a trusted CA
1638 */
1639 *flags &= ~BADCERT_NOT_TRUSTED;
1640 break;
1641 }
1642
1643 trust_ca = trust_ca->next;
1644 }
1645
1646 if( *flags != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001647 return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +00001648
1649 return( 0 );
1650}
1651
1652/*
1653 * Unallocate all certificate data
1654 */
1655void x509_free( x509_cert *crt )
1656{
1657 x509_cert *cert_cur = crt;
1658 x509_cert *cert_prv;
1659 x509_name *name_cur;
1660 x509_name *name_prv;
1661
1662 if( crt == NULL )
1663 return;
1664
1665 do
1666 {
1667 rsa_free( &cert_cur->rsa );
1668
1669 name_cur = cert_cur->issuer.next;
1670 while( name_cur != NULL )
1671 {
1672 name_prv = name_cur;
1673 name_cur = name_cur->next;
1674 memset( name_prv, 0, sizeof( x509_name ) );
1675 free( name_prv );
1676 }
1677
1678 name_cur = cert_cur->subject.next;
1679 while( name_cur != NULL )
1680 {
1681 name_prv = name_cur;
1682 name_cur = name_cur->next;
1683 memset( name_prv, 0, sizeof( x509_name ) );
1684 free( name_prv );
1685 }
1686
1687 if( cert_cur->raw.p != NULL )
1688 {
1689 memset( cert_cur->raw.p, 0, cert_cur->raw.len );
1690 free( cert_cur->raw.p );
1691 }
1692
1693 cert_cur = cert_cur->next;
1694 }
1695 while( cert_cur != NULL );
1696
1697 cert_cur = crt;
1698 do
1699 {
1700 cert_prv = cert_cur;
1701 cert_cur = cert_cur->next;
1702
1703 memset( cert_prv, 0, sizeof( x509_cert ) );
1704 if( cert_prv != crt )
1705 free( cert_prv );
1706 }
1707 while( cert_cur != NULL );
1708}
1709
Paul Bakker40e46942009-01-03 21:51:57 +00001710#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00001711
Paul Bakker40e46942009-01-03 21:51:57 +00001712#include "polarssl/certs.h"
Paul Bakker5121ce52009-01-03 21:22:43 +00001713
1714/*
1715 * Checkup routine
1716 */
1717int x509_self_test( int verbose )
1718{
1719 int ret, i, j;
1720 x509_cert cacert;
1721 x509_cert clicert;
1722 rsa_context rsa;
1723
1724 if( verbose != 0 )
1725 printf( " X.509 certificate load: " );
1726
1727 memset( &clicert, 0, sizeof( x509_cert ) );
1728
1729 ret = x509parse_crt( &clicert, (unsigned char *) test_cli_crt,
1730 strlen( test_cli_crt ) );
1731 if( ret != 0 )
1732 {
1733 if( verbose != 0 )
1734 printf( "failed\n" );
1735
1736 return( ret );
1737 }
1738
1739 memset( &cacert, 0, sizeof( x509_cert ) );
1740
1741 ret = x509parse_crt( &cacert, (unsigned char *) test_ca_crt,
1742 strlen( test_ca_crt ) );
1743 if( ret != 0 )
1744 {
1745 if( verbose != 0 )
1746 printf( "failed\n" );
1747
1748 return( ret );
1749 }
1750
1751 if( verbose != 0 )
1752 printf( "passed\n X.509 private key load: " );
1753
1754 i = strlen( test_ca_key );
1755 j = strlen( test_ca_pwd );
1756
1757 if( ( ret = x509parse_key( &rsa,
1758 (unsigned char *) test_ca_key, i,
1759 (unsigned char *) test_ca_pwd, j ) ) != 0 )
1760 {
1761 if( verbose != 0 )
1762 printf( "failed\n" );
1763
1764 return( ret );
1765 }
1766
1767 if( verbose != 0 )
1768 printf( "passed\n X.509 signature verify: ");
1769
1770 ret = x509parse_verify( &clicert, &cacert, "Joe User", &i );
1771 if( ret != 0 )
1772 {
1773 if( verbose != 0 )
1774 printf( "failed\n" );
1775
1776 return( ret );
1777 }
1778
1779 if( verbose != 0 )
1780 printf( "passed\n\n" );
1781
1782 x509_free( &cacert );
1783 x509_free( &clicert );
1784 rsa_free( &rsa );
1785
1786 return( 0 );
1787}
1788
1789#endif
1790
1791#endif