bugfixes; build system changed again %-)
[syren.git] / src / xyssl / x509parse.c
blob638a09d4bb2b7f8ec9afa2e235a33baf609d5871
1 /*
2 * X.509 certificate and private key decoding
4 * Copyright (C) 2006-2007 Christophe Devine
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License, version 2.1 as published by the Free Software Foundation.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 * MA 02110-1301 USA
21 * The ITU-T X.509 standard defines a certificat format for PKI.
23 * http://www.ietf.org/rfc/rfc2459.txt
24 * http://www.ietf.org/rfc/rfc3279.txt
26 * ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
28 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
29 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
32 #include "xyssl/config.h"
34 #if defined(XYSSL_X509_PARSE_C)
36 #include "xyssl/x509.h"
37 #include "xyssl/base64.h"
38 #include "xyssl/des.h"
39 #include "xyssl/md2.h"
40 #include "xyssl/md4.h"
41 #include "xyssl/md5.h"
42 #include "xyssl/sha1.h"
44 #include <string.h>
45 #include <stdlib.h>
46 #include <stdio.h>
47 #include <time.h>
50 * ASN.1 DER decoding routines
52 static int asn1_get_len( unsigned char **p,
53 unsigned char *end,
54 int *len )
56 if( ( end - *p ) < 1 )
57 return( XYSSL_ERR_ASN1_OUT_OF_DATA );
59 if( ( **p & 0x80 ) == 0 )
60 *len = *(*p)++;
61 else
63 switch( **p & 0x7F )
65 case 1:
66 if( ( end - *p ) < 2 )
67 return( XYSSL_ERR_ASN1_OUT_OF_DATA );
69 *len = (*p)[1];
70 (*p) += 2;
71 break;
73 case 2:
74 if( ( end - *p ) < 3 )
75 return( XYSSL_ERR_ASN1_OUT_OF_DATA );
77 *len = ( (*p)[1] << 8 ) | (*p)[2];
78 (*p) += 3;
79 break;
81 default:
82 return( XYSSL_ERR_ASN1_INVALID_LENGTH );
83 break;
87 if( *len > (int) ( end - *p ) )
88 return( XYSSL_ERR_ASN1_OUT_OF_DATA );
90 return( 0 );
93 static int asn1_get_tag( unsigned char **p,
94 unsigned char *end,
95 int *len, int tag )
97 if( ( end - *p ) < 1 )
98 return( XYSSL_ERR_ASN1_OUT_OF_DATA );
100 if( **p != tag )
101 return( XYSSL_ERR_ASN1_UNEXPECTED_TAG );
103 (*p)++;
105 return( asn1_get_len( p, end, len ) );
108 static int asn1_get_bool( unsigned char **p,
109 unsigned char *end,
110 int *val )
112 int ret, len;
114 if( ( ret = asn1_get_tag( p, end, &len, ASN1_BOOLEAN ) ) != 0 )
115 return( ret );
117 if( len != 1 )
118 return( XYSSL_ERR_ASN1_INVALID_LENGTH );
120 *val = ( **p != 0 ) ? 1 : 0;
121 (*p)++;
123 return( 0 );
126 static int asn1_get_int( unsigned char **p,
127 unsigned char *end,
128 int *val )
130 int ret, len;
132 if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
133 return( ret );
135 if( len > (int) sizeof( int ) || ( **p & 0x80 ) != 0 )
136 return( XYSSL_ERR_ASN1_INVALID_LENGTH );
138 *val = 0;
140 while( len-- > 0 )
142 *val = ( *val << 8 ) | **p;
143 (*p)++;
146 return( 0 );
149 static int asn1_get_mpi( unsigned char **p,
150 unsigned char *end,
151 mpi *X )
153 int ret, len;
155 if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
156 return( ret );
158 ret = mpi_read_binary( X, *p, len );
160 *p += len;
162 return( ret );
166 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
168 static int x509_get_version( unsigned char **p,
169 unsigned char *end,
170 int *ver )
172 int ret, len;
174 if( ( ret = asn1_get_tag( p, end, &len,
175 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) != 0 )
177 if( ret == XYSSL_ERR_ASN1_UNEXPECTED_TAG )
178 return( *ver = 0 );
180 return( ret );
183 end = *p + len;
185 if( ( ret = asn1_get_int( p, end, ver ) ) != 0 )
186 return( XYSSL_ERR_X509_CERT_INVALID_VERSION | ret );
188 if( *p != end )
189 return( XYSSL_ERR_X509_CERT_INVALID_VERSION |
190 XYSSL_ERR_ASN1_LENGTH_MISMATCH );
192 return( 0 );
196 * CertificateSerialNumber ::= INTEGER
198 static int x509_get_serial( unsigned char **p,
199 unsigned char *end,
200 x509_buf *serial )
202 int ret;
204 if( ( end - *p ) < 1 )
205 return( XYSSL_ERR_X509_CERT_INVALID_SERIAL |
206 XYSSL_ERR_ASN1_OUT_OF_DATA );
208 if( **p != ( ASN1_CONTEXT_SPECIFIC | ASN1_PRIMITIVE | 2 ) &&
209 **p != ASN1_INTEGER )
210 return( XYSSL_ERR_X509_CERT_INVALID_SERIAL |
211 XYSSL_ERR_ASN1_UNEXPECTED_TAG );
213 serial->tag = *(*p)++;
215 if( ( ret = asn1_get_len( p, end, &serial->len ) ) != 0 )
216 return( XYSSL_ERR_X509_CERT_INVALID_SERIAL | ret );
218 serial->p = *p;
219 *p += serial->len;
221 return( 0 );
225 * AlgorithmIdentifier ::= SEQUENCE {
226 * algorithm OBJECT IDENTIFIER,
227 * parameters ANY DEFINED BY algorithm OPTIONAL }
229 static int x509_get_alg( unsigned char **p,
230 unsigned char *end,
231 x509_buf *alg )
233 int ret, len;
235 if( ( ret = asn1_get_tag( p, end, &len,
236 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
237 return( XYSSL_ERR_X509_CERT_INVALID_ALG | ret );
239 end = *p + len;
240 alg->tag = **p;
242 if( ( ret = asn1_get_tag( p, end, &alg->len, ASN1_OID ) ) != 0 )
243 return( XYSSL_ERR_X509_CERT_INVALID_ALG | ret );
245 alg->p = *p;
246 *p += alg->len;
248 if( *p == end )
249 return( 0 );
252 * assume the algorithm parameters must be NULL
254 if( ( ret = asn1_get_tag( p, end, &len, ASN1_NULL ) ) != 0 )
255 return( XYSSL_ERR_X509_CERT_INVALID_ALG | ret );
257 if( *p != end )
258 return( XYSSL_ERR_X509_CERT_INVALID_ALG |
259 XYSSL_ERR_ASN1_LENGTH_MISMATCH );
261 return( 0 );
265 * RelativeDistinguishedName ::=
266 * SET OF AttributeTypeAndValue
268 * AttributeTypeAndValue ::= SEQUENCE {
269 * type AttributeType,
270 * value AttributeValue }
272 * AttributeType ::= OBJECT IDENTIFIER
274 * AttributeValue ::= ANY DEFINED BY AttributeType
276 static int x509_get_name( unsigned char **p,
277 unsigned char *end,
278 x509_name *cur )
280 int ret, len;
281 unsigned char *end2;
282 x509_buf *oid;
283 x509_buf *val;
285 if( ( ret = asn1_get_tag( p, end, &len,
286 ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 )
287 return( XYSSL_ERR_X509_CERT_INVALID_NAME | ret );
289 end2 = end;
290 end = *p + len;
292 if( ( ret = asn1_get_tag( p, end, &len,
293 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
294 return( XYSSL_ERR_X509_CERT_INVALID_NAME | ret );
296 if( *p + len != end )
297 return( XYSSL_ERR_X509_CERT_INVALID_NAME |
298 XYSSL_ERR_ASN1_LENGTH_MISMATCH );
300 oid = &cur->oid;
301 oid->tag = **p;
303 if( ( ret = asn1_get_tag( p, end, &oid->len, ASN1_OID ) ) != 0 )
304 return( XYSSL_ERR_X509_CERT_INVALID_NAME | ret );
306 oid->p = *p;
307 *p += oid->len;
309 if( ( end - *p ) < 1 )
310 return( XYSSL_ERR_X509_CERT_INVALID_NAME |
311 XYSSL_ERR_ASN1_OUT_OF_DATA );
313 if( **p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING &&
314 **p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING &&
315 **p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING )
316 return( XYSSL_ERR_X509_CERT_INVALID_NAME |
317 XYSSL_ERR_ASN1_UNEXPECTED_TAG );
319 val = &cur->val;
320 val->tag = *(*p)++;
322 if( ( ret = asn1_get_len( p, end, &val->len ) ) != 0 )
323 return( XYSSL_ERR_X509_CERT_INVALID_NAME | ret );
325 val->p = *p;
326 *p += val->len;
328 cur->next = NULL;
330 if( *p != end )
331 return( XYSSL_ERR_X509_CERT_INVALID_NAME |
332 XYSSL_ERR_ASN1_LENGTH_MISMATCH );
335 * recurse until end of SEQUENCE is reached
337 if( *p == end2 )
338 return( 0 );
340 cur->next = (x509_name *) malloc(
341 sizeof( x509_name ) );
343 if( cur->next == NULL )
344 return( 1 );
346 return( x509_get_name( p, end2, cur->next ) );
350 * Validity ::= SEQUENCE {
351 * notBefore Time,
352 * notAfter Time }
354 * Time ::= CHOICE {
355 * utcTime UTCTime,
356 * generalTime GeneralizedTime }
358 static int x509_get_dates( unsigned char **p,
359 unsigned char *end,
360 x509_time *from,
361 x509_time *to )
363 int ret, len;
364 char date[64];
366 if( ( ret = asn1_get_tag( p, end, &len,
367 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
368 return( XYSSL_ERR_X509_CERT_INVALID_DATE | ret );
370 end = *p + len;
373 * TODO: also handle GeneralizedTime
375 if( ( ret = asn1_get_tag( p, end, &len, ASN1_UTC_TIME ) ) != 0 )
376 return( XYSSL_ERR_X509_CERT_INVALID_DATE | ret );
378 memset( date, 0, sizeof( date ) );
379 memcpy( date, *p, ( len < (int) sizeof( date ) - 1 ) ?
380 len : (int) sizeof( date ) - 1 );
382 if( sscanf( date, "%2d%2d%2d%2d%2d%2d",
383 &from->year, &from->mon, &from->day,
384 &from->hour, &from->min, &from->sec ) < 5 )
385 return( XYSSL_ERR_X509_CERT_INVALID_DATE );
387 from->year += 100 * ( from->year < 90 );
388 from->year += 1900;
390 *p += len;
392 if( ( ret = asn1_get_tag( p, end, &len, ASN1_UTC_TIME ) ) != 0 )
393 return( XYSSL_ERR_X509_CERT_INVALID_DATE | ret );
395 memset( date, 0, sizeof( date ) );
396 memcpy( date, *p, ( len < (int) sizeof( date ) - 1 ) ?
397 len : (int) sizeof( date ) - 1 );
399 if( sscanf( date, "%2d%2d%2d%2d%2d%2d",
400 &to->year, &to->mon, &to->day,
401 &to->hour, &to->min, &to->sec ) < 5 )
402 return( XYSSL_ERR_X509_CERT_INVALID_DATE );
404 to->year += 100 * ( to->year < 90 );
405 to->year += 1900;
407 *p += len;
409 if( *p != end )
410 return( XYSSL_ERR_X509_CERT_INVALID_DATE |
411 XYSSL_ERR_ASN1_LENGTH_MISMATCH );
413 return( 0 );
417 * SubjectPublicKeyInfo ::= SEQUENCE {
418 * algorithm AlgorithmIdentifier,
419 * subjectPublicKey BIT STRING }
421 static int x509_get_pubkey( unsigned char **p,
422 unsigned char *end,
423 x509_buf *pk_alg_oid,
424 mpi *N, mpi *E )
426 int ret, len;
427 unsigned char *end2;
429 if( ( ret = x509_get_alg( p, end, pk_alg_oid ) ) != 0 )
430 return( ret );
433 * only RSA public keys handled at this time
435 if( pk_alg_oid->len != 9 ||
436 memcmp( pk_alg_oid->p, OID_PKCS1_RSA, 9 ) != 0 )
437 return( XYSSL_ERR_X509_CERT_UNKNOWN_PK_ALG );
439 if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 )
440 return( XYSSL_ERR_X509_CERT_INVALID_PUBKEY | ret );
442 if( ( end - *p ) < 1 )
443 return( XYSSL_ERR_X509_CERT_INVALID_PUBKEY |
444 XYSSL_ERR_ASN1_OUT_OF_DATA );
446 end2 = *p + len;
448 if( *(*p)++ != 0 )
449 return( XYSSL_ERR_X509_CERT_INVALID_PUBKEY );
452 * RSAPublicKey ::= SEQUENCE {
453 * modulus INTEGER, -- n
454 * publicExponent INTEGER -- e
457 if( ( ret = asn1_get_tag( p, end2, &len,
458 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
459 return( XYSSL_ERR_X509_CERT_INVALID_PUBKEY | ret );
461 if( *p + len != end2 )
462 return( XYSSL_ERR_X509_CERT_INVALID_PUBKEY |
463 XYSSL_ERR_ASN1_LENGTH_MISMATCH );
465 if( ( ret = asn1_get_mpi( p, end2, N ) ) != 0 ||
466 ( ret = asn1_get_mpi( p, end2, E ) ) != 0 )
467 return( XYSSL_ERR_X509_CERT_INVALID_PUBKEY | ret );
469 if( *p != end )
470 return( XYSSL_ERR_X509_CERT_INVALID_PUBKEY |
471 XYSSL_ERR_ASN1_LENGTH_MISMATCH );
473 return( 0 );
476 static int x509_get_sig( unsigned char **p,
477 unsigned char *end,
478 x509_buf *sig )
480 int ret, len;
482 sig->tag = **p;
484 if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 )
485 return( XYSSL_ERR_X509_CERT_INVALID_SIGNATURE | ret );
487 if( --len < 1 || *(*p)++ != 0 )
488 return( XYSSL_ERR_X509_CERT_INVALID_SIGNATURE );
490 sig->len = len;
491 sig->p = *p;
493 *p += len;
495 return( 0 );
499 * X.509 v2/v3 unique identifier (not parsed)
501 static int x509_get_uid( unsigned char **p,
502 unsigned char *end,
503 x509_buf *uid, int n )
505 int ret;
507 if( *p == end )
508 return( 0 );
510 uid->tag = **p;
512 if( ( ret = asn1_get_tag( p, end, &uid->len,
513 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | n ) ) != 0 )
515 if( ret == XYSSL_ERR_ASN1_UNEXPECTED_TAG )
516 return( 0 );
518 return( ret );
521 uid->p = *p;
522 *p += uid->len;
524 return( 0 );
528 * X.509 v3 extensions (only BasicConstraints are parsed)
530 static int x509_get_ext( unsigned char **p,
531 unsigned char *end,
532 x509_buf *ext,
533 int *ca_istrue,
534 int *max_pathlen )
536 int ret, len;
537 int is_critical = 1;
538 int is_cacert = 0;
539 unsigned char *end2;
541 if( *p == end )
542 return( 0 );
544 ext->tag = **p;
546 if( ( ret = asn1_get_tag( p, end, &ext->len,
547 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) ) != 0 )
549 if( ret == XYSSL_ERR_ASN1_UNEXPECTED_TAG )
550 return( 0 );
552 return( ret );
555 ext->p = *p;
556 end = *p + ext->len;
559 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
561 * Extension ::= SEQUENCE {
562 * extnID OBJECT IDENTIFIER,
563 * critical BOOLEAN DEFAULT FALSE,
564 * extnValue OCTET STRING }
566 if( ( ret = asn1_get_tag( p, end, &len,
567 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
568 return( XYSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
570 if( end != *p + len )
571 return( XYSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
572 XYSSL_ERR_ASN1_LENGTH_MISMATCH );
574 while( *p < end )
576 if( ( ret = asn1_get_tag( p, end, &len,
577 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
578 return( XYSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
580 if( memcmp( *p, "\x06\x03\x55\x1D\x13", 5 ) != 0 )
582 *p += len;
583 continue;
586 *p += 5;
588 if( ( ret = asn1_get_bool( p, end, &is_critical ) ) != 0 &&
589 ( ret != XYSSL_ERR_ASN1_UNEXPECTED_TAG ) )
590 return( XYSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
592 if( ( ret = asn1_get_tag( p, end, &len,
593 ASN1_OCTET_STRING ) ) != 0 )
594 return( XYSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
597 * BasicConstraints ::= SEQUENCE {
598 * cA BOOLEAN DEFAULT FALSE,
599 * pathLenConstraint INTEGER (0..MAX) OPTIONAL }
601 end2 = *p + len;
603 if( ( ret = asn1_get_tag( p, end2, &len,
604 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
605 return( XYSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
607 if( *p == end2 )
608 continue;
610 if( ( ret = asn1_get_bool( p, end2, &is_cacert ) ) != 0 )
611 return( XYSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
613 if( *p == end2 )
614 continue;
616 if( ( ret = asn1_get_int( p, end2, max_pathlen ) ) != 0 )
617 return( XYSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
619 if( *p != end2 )
620 return( XYSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
621 XYSSL_ERR_ASN1_LENGTH_MISMATCH );
623 max_pathlen++;
626 if( *p != end )
627 return( XYSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
628 XYSSL_ERR_ASN1_LENGTH_MISMATCH );
630 *ca_istrue = is_critical & is_cacert;
632 return( 0 );
636 * Parse one or more certificates and add them to the chained list
638 int x509parse_crt( x509_cert *chain, unsigned char *buf, int buflen )
640 int ret, len;
641 unsigned char *s1, *s2;
642 unsigned char *p, *end;
643 x509_cert *crt;
645 crt = chain;
647 while( crt->version != 0 )
648 crt = crt->next;
651 * check if the certificate is encoded in base64
653 s1 = (unsigned char *) strstr( (char *) buf,
654 "-----BEGIN CERTIFICATE-----" );
656 if( s1 != NULL )
658 s2 = (unsigned char *) strstr( (char *) buf,
659 "-----END CERTIFICATE-----" );
661 if( s2 == NULL || s2 <= s1 )
662 return( XYSSL_ERR_X509_CERT_INVALID_PEM );
664 s1 += 27;
665 if( *s1 == '\r' ) s1++;
666 if( *s1 == '\n' ) s1++;
667 else return( XYSSL_ERR_X509_CERT_INVALID_PEM );
670 * get the DER data length and decode the buffer
672 len = 0;
673 ret = base64_decode( NULL, &len, s1, s2 - s1 );
675 if( ret == XYSSL_ERR_BASE64_INVALID_CHARACTER )
676 return( XYSSL_ERR_X509_CERT_INVALID_PEM | ret );
678 if( ( p = (unsigned char *) malloc( len ) ) == NULL )
679 return( 1 );
681 if( ( ret = base64_decode( p, &len, s1, s2 - s1 ) ) != 0 )
683 free( p );
684 return( XYSSL_ERR_X509_CERT_INVALID_PEM | ret );
688 * update the buffer size and offset
690 s2 += 25;
691 if( *s2 == '\r' ) s2++;
692 if( *s2 == '\n' ) s2++;
693 else return( XYSSL_ERR_X509_CERT_INVALID_PEM );
695 buflen -= s2 - buf;
696 buf = s2;
698 else
701 * nope, copy the raw DER data
703 p = (unsigned char *) malloc( len = buflen );
705 if( p == NULL )
706 return( 1 );
708 memcpy( p, buf, buflen );
710 buflen = 0;
713 crt->raw.p = p;
714 crt->raw.len = len;
715 end = p + len;
718 * Certificate ::= SEQUENCE {
719 * tbsCertificate TBSCertificate,
720 * signatureAlgorithm AlgorithmIdentifier,
721 * signatureValue BIT STRING }
723 if( ( ret = asn1_get_tag( &p, end, &len,
724 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
726 x509_free( crt );
727 return( XYSSL_ERR_X509_CERT_INVALID_FORMAT );
730 if( len != (int) ( end - p ) )
732 x509_free( crt );
733 return( XYSSL_ERR_X509_CERT_INVALID_FORMAT |
734 XYSSL_ERR_ASN1_LENGTH_MISMATCH );
738 * TBSCertificate ::= SEQUENCE {
740 crt->tbs.p = p;
742 if( ( ret = asn1_get_tag( &p, end, &len,
743 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
745 x509_free( crt );
746 return( XYSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
749 end = p + len;
750 crt->tbs.len = end - crt->tbs.p;
753 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
755 * CertificateSerialNumber ::= INTEGER
757 * signature AlgorithmIdentifier
759 if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 ||
760 ( ret = x509_get_serial( &p, end, &crt->serial ) ) != 0 ||
761 ( ret = x509_get_alg( &p, end, &crt->sig_oid1 ) ) != 0 )
763 x509_free( crt );
764 return( ret );
767 crt->version++;
769 if( crt->version > 3 )
771 x509_free( crt );
772 return( XYSSL_ERR_X509_CERT_UNKNOWN_VERSION );
775 if( crt->sig_oid1.len != 9 ||
776 memcmp( crt->sig_oid1.p, OID_PKCS1, 8 ) != 0 )
778 x509_free( crt );
779 return( XYSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
782 if( crt->sig_oid1.p[8] < 2 ||
783 crt->sig_oid1.p[8] > 5 )
785 x509_free( crt );
786 return( XYSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
790 * issuer Name
792 crt->issuer_raw.p = p;
794 if( ( ret = asn1_get_tag( &p, end, &len,
795 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
797 x509_free( crt );
798 return( XYSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
801 if( ( ret = x509_get_name( &p, p + len, &crt->issuer ) ) != 0 )
803 x509_free( crt );
804 return( ret );
807 crt->issuer_raw.len = p - crt->issuer_raw.p;
810 * Validity ::= SEQUENCE {
811 * notBefore Time,
812 * notAfter Time }
815 if( ( ret = x509_get_dates( &p, end, &crt->valid_from,
816 &crt->valid_to ) ) != 0 )
818 x509_free( crt );
819 return( ret );
823 * subject Name
825 crt->subject_raw.p = p;
827 if( ( ret = asn1_get_tag( &p, end, &len,
828 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
830 x509_free( crt );
831 return( XYSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
834 if( ( ret = x509_get_name( &p, p + len, &crt->subject ) ) != 0 )
836 x509_free( crt );
837 return( ret );
840 crt->subject_raw.len = p - crt->subject_raw.p;
843 * SubjectPublicKeyInfo ::= SEQUENCE
844 * algorithm AlgorithmIdentifier,
845 * subjectPublicKey BIT STRING }
847 if( ( ret = asn1_get_tag( &p, end, &len,
848 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
850 x509_free( crt );
851 return( XYSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
854 if( ( ret = x509_get_pubkey( &p, p + len, &crt->pk_oid,
855 &crt->rsa.N, &crt->rsa.E ) ) != 0 )
857 x509_free( crt );
858 return( ret );
861 if( ( ret = rsa_check_pubkey( &crt->rsa ) ) != 0 )
863 x509_free( crt );
864 return( ret );
867 crt->rsa.len = mpi_size( &crt->rsa.N );
870 * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
871 * -- If present, version shall be v2 or v3
872 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
873 * -- If present, version shall be v2 or v3
874 * extensions [3] EXPLICIT Extensions OPTIONAL
875 * -- If present, version shall be v3
877 if( crt->version == 2 || crt->version == 3 )
879 ret = x509_get_uid( &p, end, &crt->issuer_id, 1 );
880 if( ret != 0 )
882 x509_free( crt );
883 return( ret );
887 if( crt->version == 2 || crt->version == 3 )
889 ret = x509_get_uid( &p, end, &crt->subject_id, 2 );
890 if( ret != 0 )
892 x509_free( crt );
893 return( ret );
897 if( crt->version == 3 )
899 ret = x509_get_ext( &p, end, &crt->v3_ext,
900 &crt->ca_istrue, &crt->max_pathlen );
901 if( ret != 0 )
903 x509_free( crt );
904 return( ret );
908 if( p != end )
910 x509_free( crt );
911 return( XYSSL_ERR_X509_CERT_INVALID_FORMAT |
912 XYSSL_ERR_ASN1_LENGTH_MISMATCH );
915 end = crt->raw.p + crt->raw.len;
918 * signatureAlgorithm AlgorithmIdentifier,
919 * signatureValue BIT STRING
921 if( ( ret = x509_get_alg( &p, end, &crt->sig_oid2 ) ) != 0 )
923 x509_free( crt );
924 return( ret );
927 if( memcmp( crt->sig_oid1.p, crt->sig_oid2.p, 9 ) != 0 )
929 x509_free( crt );
930 return( XYSSL_ERR_X509_CERT_SIG_MISMATCH );
933 if( ( ret = x509_get_sig( &p, end, &crt->sig ) ) != 0 )
935 x509_free( crt );
936 return( ret );
939 if( p != end )
941 x509_free( crt );
942 return( XYSSL_ERR_X509_CERT_INVALID_FORMAT |
943 XYSSL_ERR_ASN1_LENGTH_MISMATCH );
946 crt->next = (x509_cert *) malloc( sizeof( x509_cert ) );
948 if( crt->next == NULL )
950 x509_free( crt );
951 return( 1 );
954 crt = crt->next;
955 memset( crt, 0, sizeof( x509_cert ) );
957 if( buflen > 0 )
958 return( x509parse_crt( crt, buf, buflen ) );
960 return( 0 );
964 * Load one or more certificates and add them to the chained list
966 int x509parse_crtfile( x509_cert *chain, char *path )
968 int ret;
969 FILE *f;
970 size_t n;
971 unsigned char *buf;
973 if( ( f = fopen( path, "rb" ) ) == NULL )
974 return( 1 );
976 fseek( f, 0, SEEK_END );
977 n = (size_t) ftell( f );
978 fseek( f, 0, SEEK_SET );
980 if( ( buf = (unsigned char *) malloc( n + 1 ) ) == NULL )
981 return( 1 );
983 if( fread( buf, 1, n, f ) != n )
985 fclose( f );
986 free( buf );
987 return( 1 );
990 buf[n] = '\0';
992 ret = x509parse_crt( chain, buf, (int) n );
994 memset( buf, 0, n + 1 );
995 free( buf );
996 fclose( f );
998 return( ret );
1001 #if defined(XYSSL_DES_C)
1003 * Read a 16-byte hex string and convert it to binary
1005 static int x509_get_iv( unsigned char *s, unsigned char iv[8] )
1007 int i, j, k;
1009 memset( iv, 0, 8 );
1011 for( i = 0; i < 16; i++, s++ )
1013 if( *s >= '0' && *s <= '9' ) j = *s - '0'; else
1014 if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else
1015 if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else
1016 return( XYSSL_ERR_X509_KEY_INVALID_ENC_IV );
1018 k = ( ( i & 1 ) != 0 ) ? j : j << 4;
1020 iv[i >> 1] = (unsigned char)( iv[i >> 1] | k );
1023 return( 0 );
1027 * Decrypt with 3DES-CBC, using PBKDF1 for key derivation
1029 static void x509_des3_decrypt( unsigned char des3_iv[8],
1030 unsigned char *buf, int buflen,
1031 unsigned char *pwd, int pwdlen )
1033 md5_context md5_ctx;
1034 des3_context des3_ctx;
1035 unsigned char md5sum[16];
1036 unsigned char des3_key[24];
1039 * 3DES key[ 0..15] = MD5(pwd || IV)
1040 * key[16..23] = MD5(pwd || IV || 3DES key[ 0..15])
1042 md5_starts( &md5_ctx );
1043 md5_update( &md5_ctx, pwd, pwdlen );
1044 md5_update( &md5_ctx, des3_iv, 8 );
1045 md5_finish( &md5_ctx, md5sum );
1046 memcpy( des3_key, md5sum, 16 );
1048 md5_starts( &md5_ctx );
1049 md5_update( &md5_ctx, md5sum, 16 );
1050 md5_update( &md5_ctx, pwd, pwdlen );
1051 md5_update( &md5_ctx, des3_iv, 8 );
1052 md5_finish( &md5_ctx, md5sum );
1053 memcpy( des3_key + 16, md5sum, 8 );
1055 des3_set3key_dec( &des3_ctx, des3_key );
1056 des3_crypt_cbc( &des3_ctx, DES_DECRYPT, buflen,
1057 des3_iv, buf, buf );
1059 memset( &md5_ctx, 0, sizeof( md5_ctx ) );
1060 memset( &des3_ctx, 0, sizeof( des3_ctx ) );
1061 memset( md5sum, 0, 16 );
1062 memset( des3_key, 0, 24 );
1064 #endif
1067 * Parse a private RSA key
1069 int x509parse_key( rsa_context *rsa, unsigned char *buf, int buflen,
1070 unsigned char *pwd, int pwdlen )
1072 int ret, len, enc;
1073 unsigned char *s1, *s2;
1074 unsigned char *p, *end;
1075 unsigned char des3_iv[8];
1077 s1 = (unsigned char *) strstr( (char *) buf,
1078 "-----BEGIN RSA PRIVATE KEY-----" );
1080 if( s1 != NULL )
1082 s2 = (unsigned char *) strstr( (char *) buf,
1083 "-----END RSA PRIVATE KEY-----" );
1085 if( s2 == NULL || s2 <= s1 )
1086 return( XYSSL_ERR_X509_KEY_INVALID_PEM );
1088 s1 += 31;
1089 if( *s1 == '\r' ) s1++;
1090 if( *s1 == '\n' ) s1++;
1091 else return( XYSSL_ERR_X509_KEY_INVALID_PEM );
1093 enc = 0;
1095 if( memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 )
1097 #if defined(XYSSL_DES_C)
1098 enc++;
1100 s1 += 22;
1101 if( *s1 == '\r' ) s1++;
1102 if( *s1 == '\n' ) s1++;
1103 else return( XYSSL_ERR_X509_KEY_INVALID_PEM );
1105 if( memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) != 0 )
1106 return( XYSSL_ERR_X509_KEY_UNKNOWN_ENC_ALG );
1108 s1 += 23;
1109 if( x509_get_iv( s1, des3_iv ) != 0 )
1110 return( XYSSL_ERR_X509_KEY_INVALID_ENC_IV );
1112 s1 += 16;
1113 if( *s1 == '\r' ) s1++;
1114 if( *s1 == '\n' ) s1++;
1115 else return( XYSSL_ERR_X509_KEY_INVALID_PEM );
1116 #else
1117 return( XYSSL_ERR_X509_FEATURE_UNAVAILABLE );
1118 #endif
1121 len = 0;
1122 ret = base64_decode( NULL, &len, s1, s2 - s1 );
1124 if( ret == XYSSL_ERR_BASE64_INVALID_CHARACTER )
1125 return( ret | XYSSL_ERR_X509_KEY_INVALID_PEM );
1127 if( ( buf = (unsigned char *) malloc( len ) ) == NULL )
1128 return( 1 );
1130 if( ( ret = base64_decode( buf, &len, s1, s2 - s1 ) ) != 0 )
1132 free( buf );
1133 return( ret | XYSSL_ERR_X509_KEY_INVALID_PEM );
1136 buflen = len;
1138 if( enc != 0 )
1140 #if defined(XYSSL_DES_C)
1141 if( pwd == NULL )
1143 free( buf );
1144 return( XYSSL_ERR_X509_KEY_PASSWORD_REQUIRED );
1147 x509_des3_decrypt( des3_iv, buf, buflen, pwd, pwdlen );
1149 if( buf[0] != 0x30 || buf[1] != 0x82 ||
1150 buf[4] != 0x02 || buf[5] != 0x01 )
1152 free( buf );
1153 return( XYSSL_ERR_X509_KEY_PASSWORD_MISMATCH );
1155 #else
1156 return( XYSSL_ERR_X509_FEATURE_UNAVAILABLE );
1157 #endif
1161 memset( rsa, 0, sizeof( rsa_context ) );
1163 p = buf;
1164 end = buf + buflen;
1167 * RSAPrivateKey ::= SEQUENCE {
1168 * version Version,
1169 * modulus INTEGER, -- n
1170 * publicExponent INTEGER, -- e
1171 * privateExponent INTEGER, -- d
1172 * prime1 INTEGER, -- p
1173 * prime2 INTEGER, -- q
1174 * exponent1 INTEGER, -- d mod (p-1)
1175 * exponent2 INTEGER, -- d mod (q-1)
1176 * coefficient INTEGER, -- (inverse of q) mod p
1177 * otherPrimeInfos OtherPrimeInfos OPTIONAL
1180 if( ( ret = asn1_get_tag( &p, end, &len,
1181 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1183 if( s1 != NULL )
1184 free( buf );
1186 rsa_free( rsa );
1187 return( XYSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
1190 end = p + len;
1192 if( ( ret = asn1_get_int( &p, end, &rsa->ver ) ) != 0 )
1194 if( s1 != NULL )
1195 free( buf );
1197 rsa_free( rsa );
1198 return( XYSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
1201 if( rsa->ver != 0 )
1203 if( s1 != NULL )
1204 free( buf );
1206 rsa_free( rsa );
1207 return( ret | XYSSL_ERR_X509_KEY_INVALID_VERSION );
1210 if( ( ret = asn1_get_mpi( &p, end, &rsa->N ) ) != 0 ||
1211 ( ret = asn1_get_mpi( &p, end, &rsa->E ) ) != 0 ||
1212 ( ret = asn1_get_mpi( &p, end, &rsa->D ) ) != 0 ||
1213 ( ret = asn1_get_mpi( &p, end, &rsa->P ) ) != 0 ||
1214 ( ret = asn1_get_mpi( &p, end, &rsa->Q ) ) != 0 ||
1215 ( ret = asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 ||
1216 ( ret = asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 ||
1217 ( ret = asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 )
1219 if( s1 != NULL )
1220 free( buf );
1222 rsa_free( rsa );
1223 return( ret | XYSSL_ERR_X509_KEY_INVALID_FORMAT );
1226 rsa->len = mpi_size( &rsa->N );
1228 if( p != end )
1230 if( s1 != NULL )
1231 free( buf );
1233 rsa_free( rsa );
1234 return( XYSSL_ERR_X509_KEY_INVALID_FORMAT |
1235 XYSSL_ERR_ASN1_LENGTH_MISMATCH );
1238 if( ( ret = rsa_check_privkey( rsa ) ) != 0 )
1240 if( s1 != NULL )
1241 free( buf );
1243 rsa_free( rsa );
1244 return( ret );
1247 if( s1 != NULL )
1248 free( buf );
1250 return( 0 );
1254 * Load and parse a private RSA key
1256 int x509parse_keyfile( rsa_context *rsa, char *path, char *pwd )
1258 int ret;
1259 FILE *f;
1260 size_t n;
1261 unsigned char *buf;
1263 if( ( f = fopen( path, "rb" ) ) == NULL )
1264 return( 1 );
1266 fseek( f, 0, SEEK_END );
1267 n = (size_t) ftell( f );
1268 fseek( f, 0, SEEK_SET );
1270 if( ( buf = (unsigned char *) malloc( n + 1 ) ) == NULL )
1271 return( 1 );
1273 if( fread( buf, 1, n, f ) != n )
1275 fclose( f );
1276 free( buf );
1277 return( 1 );
1280 buf[n] = '\0';
1282 if( pwd == NULL )
1283 ret = x509parse_key( rsa, buf, (int) n, NULL, 0 );
1284 else
1285 ret = x509parse_key( rsa, buf, (int) n,
1286 (unsigned char *) pwd, strlen( pwd ) );
1288 memset( buf, 0, n + 1 );
1289 free( buf );
1290 fclose( f );
1292 return( ret );
1295 #if defined _MSC_VER && !defined snprintf
1296 #define snprintf _snprintf
1297 #endif
1300 * Store the name in printable form into buf; no more
1301 * than (end - buf) characters will be written
1303 int x509parse_dn_gets( char *buf, char *end, x509_name *dn )
1305 int i;
1306 unsigned char c;
1307 x509_name *name;
1308 char s[128], *p;
1310 memset( s, 0, sizeof( s ) );
1312 name = dn;
1313 p = buf;
1315 while( name != NULL )
1317 if( name != dn )
1318 p += snprintf( p, end - p, ", " );
1320 if( memcmp( name->oid.p, OID_X520, 2 ) == 0 )
1322 switch( name->oid.p[2] )
1324 case X520_COMMON_NAME:
1325 p += snprintf( p, end - p, "CN=" ); break;
1327 case X520_COUNTRY:
1328 p += snprintf( p, end - p, "C=" ); break;
1330 case X520_LOCALITY:
1331 p += snprintf( p, end - p, "L=" ); break;
1333 case X520_STATE:
1334 p += snprintf( p, end - p, "ST=" ); break;
1336 case X520_ORGANIZATION:
1337 p += snprintf( p, end - p, "O=" ); break;
1339 case X520_ORG_UNIT:
1340 p += snprintf( p, end - p, "OU=" ); break;
1342 default:
1343 p += snprintf( p, end - p, "0x%02X=",
1344 name->oid.p[2] );
1345 break;
1348 else if( memcmp( name->oid.p, OID_PKCS9, 8 ) == 0 )
1350 switch( name->oid.p[8] )
1352 case PKCS9_EMAIL:
1353 p += snprintf( p, end - p, "emailAddress=" ); break;
1355 default:
1356 p += snprintf( p, end - p, "0x%02X=",
1357 name->oid.p[8] );
1358 break;
1361 else
1362 p += snprintf( p, end - p, "\?\?=" );
1364 for( i = 0; i < name->val.len; i++ )
1366 if( i >= (int) sizeof( s ) - 1 )
1367 break;
1369 c = name->val.p[i];
1370 if( c < 32 || c == 127 || ( c > 128 && c < 160 ) )
1371 s[i] = '?';
1372 else s[i] = c;
1374 s[i] = '\0';
1375 p += snprintf( p, end - p, "%s", s );
1376 name = name->next;
1379 return( p - buf );
1383 * Return an informational string about the
1384 * certificate, or NULL if memory allocation failed
1386 char *x509parse_cert_info( char *prefix, x509_cert *crt )
1388 int i, n;
1389 char *buf, *p, *end;
1391 if( ( buf = (char *) malloc( 4096 ) ) == NULL )
1392 return( NULL );
1394 memset( buf, 0, 4096 );
1396 p = buf;
1397 end = buf + 4096 - 1;
1399 p += snprintf( p, end - p, "%scert. version : %d\n",
1400 prefix, crt->version );
1401 p += snprintf( p, end - p, "%sserial number : ",
1402 prefix );
1404 n = ( crt->serial.len <= 32 )
1405 ? crt->serial.len : 32;
1407 for( i = 1; i < n; i++ )
1408 p += snprintf( p, end - p, "%02X%s",
1409 crt->serial.p[i], ( i < n - 1 ) ? ":" : "" );
1411 p += snprintf( p, end - p, "\n%sissuer name : ", prefix );
1412 p += x509parse_dn_gets( p, end, &crt->issuer );
1414 p += snprintf( p, end - p, "\n%ssubject name : ", prefix );
1415 p += x509parse_dn_gets( p, end, &crt->subject );
1417 p += snprintf( p, end - p, "\n%sissued on : " \
1418 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
1419 crt->valid_from.year, crt->valid_from.mon,
1420 crt->valid_from.day, crt->valid_from.hour,
1421 crt->valid_from.min, crt->valid_from.sec );
1423 p += snprintf( p, end - p, "\n%sexpires on : " \
1424 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
1425 crt->valid_to.year, crt->valid_to.mon,
1426 crt->valid_to.day, crt->valid_to.hour,
1427 crt->valid_to.min, crt->valid_to.sec );
1429 p += snprintf( p, end - p, "\n%ssigned using : RSA+", prefix );
1431 switch( crt->sig_oid1.p[8] )
1433 case RSA_MD2 : p += snprintf( p, end - p, "MD2" ); break;
1434 case RSA_MD4 : p += snprintf( p, end - p, "MD4" ); break;
1435 case RSA_MD5 : p += snprintf( p, end - p, "MD5" ); break;
1436 case RSA_SHA1: p += snprintf( p, end - p, "SHA1" ); break;
1437 default: p += snprintf( p, end - p, "???" ); break;
1440 p += snprintf( p, end - p, "\n%sRSA key size : %d bits\n", prefix,
1441 crt->rsa.N.n * (int) sizeof( unsigned long ) * 8 );
1443 return( buf );
1447 * Return 0 if the certificate is still valid, or BADCERT_EXPIRED
1449 int x509parse_expired( x509_cert *crt )
1451 struct tm *lt;
1452 time_t tt;
1454 tt = time( NULL );
1455 lt = localtime( &tt );
1457 if( lt->tm_year > crt->valid_to.year - 1900 )
1458 return( BADCERT_EXPIRED );
1460 if( lt->tm_year == crt->valid_to.year - 1900 &&
1461 lt->tm_mon > crt->valid_to.mon - 1 )
1462 return( BADCERT_EXPIRED );
1464 if( lt->tm_year == crt->valid_to.year - 1900 &&
1465 lt->tm_mon == crt->valid_to.mon - 1 &&
1466 lt->tm_mday > crt->valid_to.day )
1467 return( BADCERT_EXPIRED );
1469 return( 0 );
1472 static void x509_hash( unsigned char *in, int len, int alg,
1473 unsigned char *out )
1475 switch( alg )
1477 #if defined(XYSSL_MD2_C)
1478 case RSA_MD2 : md2( in, len, out ); break;
1479 #endif
1480 #if defined(XYSSL_MD4_C)
1481 case RSA_MD4 : md4( in, len, out ); break;
1482 #endif
1483 case RSA_MD5 : md5( in, len, out ); break;
1484 case RSA_SHA1 : sha1( in, len, out ); break;
1485 default:
1486 memset( out, '\xFF', len );
1487 break;
1492 * Verify the certificate validity
1494 int x509parse_verify( x509_cert *crt,
1495 x509_cert *trust_ca,
1496 char *cn, int *flags )
1498 int hash_id;
1499 int pathlen;
1500 x509_cert *cur;
1501 x509_name *name;
1502 unsigned char hash[20];
1504 *flags = x509parse_expired( crt );
1506 if( cn != NULL )
1508 name = &crt->subject;
1510 while( name != NULL )
1512 if( memcmp( name->oid.p, "\x55\x04\x03", 3 ) == 0 &&
1513 memcmp( name->val.p, cn, strlen( cn ) ) == 0 )
1514 break;
1516 name = name->next;
1519 if( name == NULL )
1520 *flags |= BADCERT_CN_MISMATCH;
1523 *flags |= BADCERT_NOT_TRUSTED;
1526 * Iterate upwards in the given cert chain,
1527 * ignoring any upper cert with CA != TRUE.
1529 cur = crt->next;
1531 pathlen = 1;
1533 while( cur->version != 0 )
1535 if( cur->ca_istrue == 0 ||
1536 crt->issuer_raw.len != cur->subject_raw.len ||
1537 memcmp( crt->issuer_raw.p, cur->subject_raw.p,
1538 crt->issuer_raw.len ) != 0 )
1540 cur = cur->next;
1541 continue;
1544 hash_id = crt->sig_oid1.p[8];
1546 x509_hash( crt->tbs.p, crt->tbs.len, hash_id, hash );
1548 if( rsa_pkcs1_verify( &cur->rsa, RSA_PUBLIC, hash_id,
1549 0, hash, crt->sig.p ) != 0 )
1550 return( XYSSL_ERR_X509_CERT_VERIFY_FAILED );
1552 pathlen++;
1554 crt = cur;
1555 cur = crt->next;
1559 * Atempt to validate topmost cert with our CA chain.
1561 while( trust_ca->version != 0 )
1563 if( crt->issuer_raw.len != trust_ca->subject_raw.len ||
1564 memcmp( crt->issuer_raw.p, trust_ca->subject_raw.p,
1565 crt->issuer_raw.len ) != 0 )
1567 trust_ca = trust_ca->next;
1568 continue;
1571 if( trust_ca->max_pathlen > 0 &&
1572 trust_ca->max_pathlen < pathlen )
1573 break;
1575 hash_id = crt->sig_oid1.p[8];
1577 x509_hash( crt->tbs.p, crt->tbs.len, hash_id, hash );
1579 if( rsa_pkcs1_verify( &trust_ca->rsa, RSA_PUBLIC, hash_id,
1580 0, hash, crt->sig.p ) == 0 )
1583 * cert. is signed by a trusted CA
1585 *flags &= ~BADCERT_NOT_TRUSTED;
1586 break;
1590 if( *flags != 0 )
1591 return( XYSSL_ERR_X509_CERT_VERIFY_FAILED );
1593 return( 0 );
1597 * Unallocate all certificate data
1599 void x509_free( x509_cert *crt )
1601 x509_cert *cert_cur = crt;
1602 x509_cert *cert_prv;
1603 x509_name *name_cur;
1604 x509_name *name_prv;
1606 if( crt == NULL )
1607 return;
1611 rsa_free( &cert_cur->rsa );
1613 name_cur = cert_cur->issuer.next;
1614 while( name_cur != NULL )
1616 name_prv = name_cur;
1617 name_cur = name_cur->next;
1618 free( name_prv );
1621 name_cur = cert_cur->subject.next;
1622 while( name_cur != NULL )
1624 name_prv = name_cur;
1625 name_cur = name_cur->next;
1626 free( name_prv );
1629 if( cert_cur->raw.p != NULL )
1630 free( cert_cur->raw.p );
1632 cert_cur = cert_cur->next;
1634 while( cert_cur != NULL );
1636 cert_cur = crt;
1639 cert_prv = cert_cur;
1640 cert_cur = cert_cur->next;
1642 if( cert_prv != crt )
1643 free( cert_prv );
1645 while( cert_cur != NULL );
1648 #if defined(XYSSL_SELF_TEST)
1650 #include "xyssl/certs.h"
1653 * Checkup routine
1655 int x509_self_test( int verbose )
1657 int ret, i, j;
1658 x509_cert cacert;
1659 x509_cert clicert;
1660 rsa_context rsa;
1662 if( verbose != 0 )
1663 printf( " X.509 certificate load: " );
1665 memset( &clicert, 0, sizeof( x509_cert ) );
1667 ret = x509parse_crt( &clicert, (unsigned char *) test_cli_crt,
1668 strlen( test_cli_crt ) );
1669 if( ret != 0 )
1671 if( verbose != 0 )
1672 printf( "failed\n" );
1674 return( ret );
1677 memset( &cacert, 0, sizeof( x509_cert ) );
1679 ret = x509parse_crt( &cacert, (unsigned char *) test_ca_crt,
1680 strlen( test_ca_crt ) );
1681 if( ret != 0 )
1683 if( verbose != 0 )
1684 printf( "failed\n" );
1686 return( ret );
1689 if( verbose != 0 )
1690 printf( "passed\n X.509 private key load: " );
1692 i = strlen( test_ca_key );
1693 j = strlen( test_ca_pwd );
1695 if( ( ret = x509parse_key( &rsa,
1696 (unsigned char *) test_ca_key, i,
1697 (unsigned char *) test_ca_pwd, j ) ) != 0 )
1699 if( verbose != 0 )
1700 printf( "failed\n" );
1702 return( ret );
1705 if( verbose != 0 )
1706 printf( "passed\n X.509 signature verify: ");
1708 ret = x509parse_verify( &clicert, &cacert, "Joe User", &i );
1709 if( ret != 0 )
1711 if( verbose != 0 )
1712 printf( "failed\n" );
1714 return( ret );
1717 if( verbose != 0 )
1718 printf( "passed\n\n" );
1720 x509_free( &cacert );
1721 x509_free( &clicert );
1722 rsa_free( &rsa );
1724 return( 0 );
1727 #endif
1729 #endif