00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifndef _CRT_SECURE_NO_DEPRECATE
00033 #define _CRT_SECURE_NO_DEPRECATE 1
00034 #endif
00035
00036 #include <string.h>
00037 #include <stdlib.h>
00038 #include <stdio.h>
00039 #include <time.h>
00040
00041 #include "xyssl/x509.h"
00042 #include "xyssl/base64.h"
00043 #include "xyssl/des.h"
00044 #include "xyssl/sha1.h"
00045 #include "xyssl/md5.h"
00046
00047 #if !defined(NO_MD4)
00048 #include "xyssl/md4.h"
00049 #endif
00050 #if !defined(NO_MD2)
00051 #include "xyssl/md2.h"
00052 #endif
00053
00054
00055
00056
00057 static int asn1_get_len( unsigned char **p,
00058 unsigned char *end,
00059 int *len )
00060 {
00061 if( ( end - *p ) < 1 )
00062 return( ERR_ASN1_OUT_OF_DATA );
00063
00064 if( ( **p & 0x80 ) == 0 )
00065 *len = *(*p)++;
00066 else
00067 {
00068 switch( **p & 0x7F )
00069 {
00070 case 1:
00071 if( ( end - *p ) < 2 )
00072 return( ERR_ASN1_OUT_OF_DATA );
00073
00074 *len = (*p)[1];
00075 (*p) += 2;
00076 break;
00077
00078 case 2:
00079 if( ( end - *p ) < 3 )
00080 return( ERR_ASN1_OUT_OF_DATA );
00081
00082 *len = ( (*p)[1] << 8 ) | (*p)[2];
00083 (*p) += 3;
00084 break;
00085
00086 default:
00087 return( ERR_ASN1_INVALID_LENGTH );
00088 break;
00089 }
00090 }
00091
00092 if( *len > (int) ( end - *p ) )
00093 return( ERR_ASN1_OUT_OF_DATA );
00094
00095 return( 0 );
00096 }
00097
00098 static int asn1_get_tag( unsigned char **p,
00099 unsigned char *end,
00100 int *len, int tag )
00101 {
00102 if( ( end - *p ) < 1 )
00103 return( ERR_ASN1_OUT_OF_DATA );
00104
00105 if( **p != tag )
00106 return( ERR_ASN1_UNEXPECTED_TAG );
00107
00108 (*p)++;
00109
00110 return( asn1_get_len( p, end, len ) );
00111 }
00112
00113 static int asn1_get_bool( unsigned char **p,
00114 unsigned char *end,
00115 int *val )
00116 {
00117 int ret, len;
00118
00119 if( ( ret = asn1_get_tag( p, end, &len, ASN1_BOOLEAN ) ) != 0 )
00120 return( ret );
00121
00122 if( len != 1 )
00123 return( ERR_ASN1_INVALID_LENGTH );
00124
00125 *val = ( **p != 0 ) ? 1 : 0;
00126 (*p)++;
00127
00128 return( 0 );
00129 }
00130
00131 static int asn1_get_int( unsigned char **p,
00132 unsigned char *end,
00133 int *val )
00134 {
00135 int ret, len;
00136
00137 if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
00138 return( ret );
00139
00140 if( len > (int) sizeof( int ) || ( **p & 0x80 ) != 0 )
00141 return( ERR_ASN1_INVALID_LENGTH );
00142
00143 *val = 0;
00144
00145 while( len-- > 0 )
00146 {
00147 *val = ( *val << 8 ) | **p;
00148 (*p)++;
00149 }
00150
00151 return( 0 );
00152 }
00153
00154 static int asn1_get_mpi( unsigned char **p,
00155 unsigned char *end,
00156 mpi *X )
00157 {
00158 int ret, len;
00159
00160 if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
00161 return( ret );
00162
00163 ret = mpi_read_binary( X, *p, len );
00164
00165 *p += len;
00166
00167 return( ret );
00168 }
00169
00170
00171
00172
00173 static int x509_get_version( unsigned char **p,
00174 unsigned char *end,
00175 int *ver )
00176 {
00177 int ret, len;
00178
00179 if( ( ret = asn1_get_tag( p, end, &len,
00180 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) != 0 )
00181 {
00182 if( ret == ERR_ASN1_UNEXPECTED_TAG )
00183 return( *ver = 0 );
00184
00185 return( ret );
00186 }
00187
00188 end = *p + len;
00189
00190 if( ( ret = asn1_get_int( p, end, ver ) ) != 0 )
00191 return( ERR_X509_CERT_INVALID_VERSION | ret );
00192
00193 if( *p != end )
00194 return( ERR_X509_CERT_INVALID_VERSION |
00195 ERR_ASN1_LENGTH_MISMATCH );
00196
00197 return( 0 );
00198 }
00199
00200
00201
00202
00203 static int x509_get_serial( unsigned char **p,
00204 unsigned char *end,
00205 x509_buf *serial )
00206 {
00207 int ret;
00208
00209 if( ( end - *p ) < 1 )
00210 return( ERR_X509_CERT_INVALID_SERIAL |
00211 ERR_ASN1_OUT_OF_DATA );
00212
00213 if( **p != ( ASN1_CONTEXT_SPECIFIC | ASN1_PRIMITIVE | 2 ) &&
00214 **p != ASN1_INTEGER )
00215 return( ERR_X509_CERT_INVALID_SERIAL |
00216 ERR_ASN1_UNEXPECTED_TAG );
00217
00218 serial->tag = *(*p)++;
00219
00220 if( ( ret = asn1_get_len( p, end, &serial->len ) ) != 0 )
00221 return( ERR_X509_CERT_INVALID_SERIAL | ret );
00222
00223 serial->p = *p;
00224 *p += serial->len;
00225
00226 return( 0 );
00227 }
00228
00229
00230
00231
00232
00233
00234 static int x509_get_alg( unsigned char **p,
00235 unsigned char *end,
00236 x509_buf *alg )
00237 {
00238 int ret, len;
00239
00240 if( ( ret = asn1_get_tag( p, end, &len,
00241 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
00242 return( ERR_X509_CERT_INVALID_ALG | ret );
00243
00244 end = *p + len;
00245 alg->tag = **p;
00246
00247 if( ( ret = asn1_get_tag( p, end, &alg->len, ASN1_OID ) ) != 0 )
00248 return( ERR_X509_CERT_INVALID_ALG | ret );
00249
00250 alg->p = *p;
00251 *p += alg->len;
00252
00253 if( *p == end )
00254 return( 0 );
00255
00256
00257
00258
00259 if( ( ret = asn1_get_tag( p, end, &len, ASN1_NULL ) ) != 0 )
00260 return( ERR_X509_CERT_INVALID_ALG | ret );
00261
00262 if( *p != end )
00263 return( ERR_X509_CERT_INVALID_ALG |
00264 ERR_ASN1_LENGTH_MISMATCH );
00265
00266 return( 0 );
00267 }
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 static int x509_get_name( unsigned char **p,
00282 unsigned char *end,
00283 x509_name *cur )
00284 {
00285 int ret, len;
00286 unsigned char *end2;
00287 x509_buf *oid;
00288 x509_buf *val;
00289
00290 if( ( ret = asn1_get_tag( p, end, &len,
00291 ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 )
00292 return( ERR_X509_CERT_INVALID_NAME | ret );
00293
00294 end2 = end;
00295 end = *p + len;
00296
00297 if( ( ret = asn1_get_tag( p, end, &len,
00298 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
00299 return( ERR_X509_CERT_INVALID_NAME | ret );
00300
00301 if( *p + len != end )
00302 return( ERR_X509_CERT_INVALID_NAME |
00303 ERR_ASN1_LENGTH_MISMATCH );
00304
00305 oid = &cur->oid;
00306 oid->tag = **p;
00307
00308 if( ( ret = asn1_get_tag( p, end, &oid->len, ASN1_OID ) ) != 0 )
00309 return( ERR_X509_CERT_INVALID_NAME | ret );
00310
00311 oid->p = *p;
00312 *p += oid->len;
00313
00314 if( ( end - *p ) < 1 )
00315 return( ERR_X509_CERT_INVALID_NAME |
00316 ERR_ASN1_OUT_OF_DATA );
00317
00318 if( **p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING &&
00319 **p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING &&
00320 **p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING )
00321 return( ERR_X509_CERT_INVALID_NAME |
00322 ERR_ASN1_UNEXPECTED_TAG );
00323
00324 val = &cur->val;
00325 val->tag = *(*p)++;
00326
00327 if( ( ret = asn1_get_len( p, end, &val->len ) ) != 0 )
00328 return( ERR_X509_CERT_INVALID_NAME | ret );
00329
00330 val->p = *p;
00331 *p += val->len;
00332
00333 cur->next = NULL;
00334
00335 if( *p != end )
00336 return( ERR_X509_CERT_INVALID_NAME |
00337 ERR_ASN1_LENGTH_MISMATCH );
00338
00339
00340
00341
00342 if( *p == end2 )
00343 return( 0 );
00344
00345 cur->next = (x509_name *) malloc(
00346 sizeof( x509_name ) );
00347
00348 if( cur->next == NULL )
00349 return( 1 );
00350
00351 return( x509_get_name( p, end2, cur->next ) );
00352 }
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363 static int x509_get_dates( unsigned char **p,
00364 unsigned char *end,
00365 x509_time *from,
00366 x509_time *to )
00367 {
00368 int ret, len;
00369 char date[64];
00370
00371 if( ( ret = asn1_get_tag( p, end, &len,
00372 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
00373 return( ERR_X509_CERT_INVALID_DATE | ret );
00374
00375 end = *p + len;
00376
00377
00378
00379
00380 if( ( ret = asn1_get_tag( p, end, &len, ASN1_UTC_TIME ) ) != 0 )
00381 return( ERR_X509_CERT_INVALID_DATE | ret );
00382
00383 memset( date, 0, sizeof( date ) );
00384 memcpy( date, *p, ( len < (int) sizeof( date ) - 1 ) ?
00385 len : (int) sizeof( date ) - 1 );
00386
00387 if( sscanf( date, "%2d%2d%2d%2d%2d%2d",
00388 &from->year, &from->mon, &from->day,
00389 &from->hour, &from->min, &from->sec ) < 5 )
00390 return( ERR_X509_CERT_INVALID_DATE );
00391
00392 from->year += 100 * ( from->year < 90 );
00393 from->year += 1900;
00394
00395 *p += len;
00396
00397 if( ( ret = asn1_get_tag( p, end, &len, ASN1_UTC_TIME ) ) != 0 )
00398 return( ERR_X509_CERT_INVALID_DATE | ret );
00399
00400 memset( date, 0, sizeof( date ) );
00401 memcpy( date, *p, ( len < (int) sizeof( date ) - 1 ) ?
00402 len : (int) sizeof( date ) - 1 );
00403
00404 if( sscanf( date, "%2d%2d%2d%2d%2d%2d",
00405 &to->year, &to->mon, &to->day,
00406 &to->hour, &to->min, &to->sec ) < 5 )
00407 return( ERR_X509_CERT_INVALID_DATE );
00408
00409 to->year += 100 * ( to->year < 90 );
00410 to->year += 1900;
00411
00412 *p += len;
00413
00414 if( *p != end )
00415 return( ERR_X509_CERT_INVALID_DATE |
00416 ERR_ASN1_LENGTH_MISMATCH );
00417
00418 return( 0 );
00419 }
00420
00421
00422
00423
00424
00425
00426 static int x509_get_pubkey( unsigned char **p,
00427 unsigned char *end,
00428 x509_buf *pk_alg_oid,
00429 mpi *N, mpi *E )
00430 {
00431 int ret, len;
00432 unsigned char *end2;
00433
00434 if( ( ret = x509_get_alg( p, end, pk_alg_oid ) ) != 0 )
00435 return( ret );
00436
00437
00438
00439
00440 if( pk_alg_oid->len != 9 ||
00441 memcmp( pk_alg_oid->p, OID_PKCS1_RSA, 9 ) != 0 )
00442 return( ERR_X509_CERT_UNKNOWN_PK_ALG );
00443
00444 if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 )
00445 return( ERR_X509_CERT_INVALID_PUBKEY | ret );
00446
00447 if( ( end - *p ) < 1 )
00448 return( ERR_X509_CERT_INVALID_PUBKEY |
00449 ERR_ASN1_OUT_OF_DATA );
00450
00451 end2 = *p + len;
00452
00453 if( *(*p)++ != 0 )
00454 return( ERR_X509_CERT_INVALID_PUBKEY );
00455
00456
00457
00458
00459
00460
00461
00462 if( ( ret = asn1_get_tag( p, end2, &len,
00463 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
00464 return( ERR_X509_CERT_INVALID_PUBKEY | ret );
00465
00466 if( *p + len != end2 )
00467 return( ERR_X509_CERT_INVALID_PUBKEY |
00468 ERR_ASN1_LENGTH_MISMATCH );
00469
00470 if( ( ret = asn1_get_mpi( p, end2, N ) ) != 0 ||
00471 ( ret = asn1_get_mpi( p, end2, E ) ) != 0 )
00472 return( ERR_X509_CERT_INVALID_PUBKEY | ret );
00473
00474 if( *p != end )
00475 return( ERR_X509_CERT_INVALID_PUBKEY |
00476 ERR_ASN1_LENGTH_MISMATCH );
00477
00478 return( 0 );
00479 }
00480
00481 static int x509_get_sig( unsigned char **p,
00482 unsigned char *end,
00483 x509_buf *sig )
00484 {
00485 int ret, len;
00486
00487 sig->tag = **p;
00488
00489 if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 )
00490 return( ERR_X509_CERT_INVALID_SIGNATURE | ret );
00491
00492 if( --len < 1 || *(*p)++ != 0 )
00493 return( ERR_X509_CERT_INVALID_SIGNATURE );
00494
00495 sig->len = len;
00496 sig->p = *p;
00497
00498 *p += len;
00499
00500 return( 0 );
00501 }
00502
00503
00504
00505
00506 static int x509_get_uid( unsigned char **p,
00507 unsigned char *end,
00508 x509_buf *uid, int n )
00509 {
00510 int ret;
00511
00512 if( *p == end )
00513 return( 0 );
00514
00515 uid->tag = **p;
00516
00517 if( ( ret = asn1_get_tag( p, end, &uid->len,
00518 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | n ) ) != 0 )
00519 {
00520 if( ret == ERR_ASN1_UNEXPECTED_TAG )
00521 return( 0 );
00522
00523 return( ret );
00524 }
00525
00526 uid->p = *p;
00527 *p += uid->len;
00528
00529 return( 0 );
00530 }
00531
00532
00533
00534
00535 static int x509_get_ext( unsigned char **p,
00536 unsigned char *end,
00537 x509_buf *ext,
00538 int *ca_istrue,
00539 int *max_pathlen )
00540 {
00541 int ret, len;
00542 int is_critical = 1;
00543 int is_cacert = 0;
00544 unsigned char *end2;
00545
00546 if( *p == end )
00547 return( 0 );
00548
00549 ext->tag = **p;
00550
00551 if( ( ret = asn1_get_tag( p, end, &ext->len,
00552 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) ) != 0 )
00553 {
00554 if( ret == ERR_ASN1_UNEXPECTED_TAG )
00555 return( 0 );
00556
00557 return( ret );
00558 }
00559
00560 ext->p = *p;
00561 end = *p + ext->len;
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571 if( ( ret = asn1_get_tag( p, end, &len,
00572 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
00573 return( ERR_X509_CERT_INVALID_EXTENSIONS | ret );
00574
00575 if( end != *p + len )
00576 return( ERR_X509_CERT_INVALID_EXTENSIONS |
00577 ERR_ASN1_LENGTH_MISMATCH );
00578
00579 while( *p < end )
00580 {
00581 if( ( ret = asn1_get_tag( p, end, &len,
00582 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
00583 return( ERR_X509_CERT_INVALID_EXTENSIONS | ret );
00584
00585 if( memcmp( *p, "\x06\x03\x55\x1D\x13", 5 ) != 0 )
00586 {
00587 *p += len;
00588 continue;
00589 }
00590
00591 *p += 5;
00592
00593 if( ( ret = asn1_get_bool( p, end, &is_critical ) ) != 0 &&
00594 ( ret != ERR_ASN1_UNEXPECTED_TAG ) )
00595 return( ERR_X509_CERT_INVALID_EXTENSIONS | ret );
00596
00597 if( ( ret = asn1_get_tag( p, end, &len,
00598 ASN1_OCTET_STRING ) ) != 0 )
00599 return( ERR_X509_CERT_INVALID_EXTENSIONS | ret );
00600
00601
00602
00603
00604
00605
00606 end2 = *p + len;
00607
00608 if( ( ret = asn1_get_tag( p, end2, &len,
00609 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
00610 return( ERR_X509_CERT_INVALID_EXTENSIONS | ret );
00611
00612 if( *p == end2 )
00613 continue;
00614
00615 if( ( ret = asn1_get_bool( p, end2, &is_cacert ) ) != 0 )
00616 return( ERR_X509_CERT_INVALID_EXTENSIONS | ret );
00617
00618 if( *p == end2 )
00619 continue;
00620
00621 if( ( ret = asn1_get_int( p, end2, max_pathlen ) ) != 0 )
00622 return( ERR_X509_CERT_INVALID_EXTENSIONS | ret );
00623
00624 if( *p != end2 )
00625 return( ERR_X509_CERT_INVALID_EXTENSIONS |
00626 ERR_ASN1_LENGTH_MISMATCH );
00627
00628 max_pathlen++;
00629 }
00630
00631 if( *p != end )
00632 return( ERR_X509_CERT_INVALID_EXTENSIONS |
00633 ERR_ASN1_LENGTH_MISMATCH );
00634
00635 *ca_istrue = is_critical & is_cacert;
00636
00637 return( 0 );
00638 }
00639
00640
00641
00642
00643 int x509_add_certs( x509_cert *chain, unsigned char *buf, int buflen )
00644 {
00645 int ret, len;
00646 unsigned char *s1, *s2;
00647 unsigned char *p, *end;
00648 x509_cert *crt;
00649
00650 crt = chain;
00651
00652 while( crt->version != 0 )
00653 crt = crt->next;
00654
00655
00656
00657
00658 s1 = (unsigned char *) strstr( (char *) buf,
00659 "-----BEGIN CERTIFICATE-----" );
00660
00661 if( s1 != NULL )
00662 {
00663 s2 = (unsigned char *) strstr( (char *) buf,
00664 "-----END CERTIFICATE-----" );
00665
00666 if( s2 == NULL || s2 <= s1 )
00667 return( ERR_X509_CERT_INVALID_PEM );
00668
00669 s1 += 27;
00670 if( *s1 == '\r' ) s1++;
00671 if( *s1 == '\n' ) s1++;
00672 else return( ERR_X509_CERT_INVALID_PEM );
00673
00674
00675
00676
00677 len = 0;
00678 ret = base64_decode( NULL, &len, s1, s2 - s1 );
00679
00680 if( ret == ERR_BASE64_INVALID_CHARACTER )
00681 return( ERR_X509_CERT_INVALID_PEM | ret );
00682
00683 if( ( p = (unsigned char *) malloc( len ) ) == NULL )
00684 return( 1 );
00685
00686 if( ( ret = base64_decode( p, &len, s1, s2 - s1 ) ) != 0 )
00687 {
00688 free( p );
00689 return( ERR_X509_CERT_INVALID_PEM | ret );
00690 }
00691
00692
00693
00694
00695 s2 += 25;
00696 if( *s2 == '\r' ) s2++;
00697 if( *s2 == '\n' ) s2++;
00698 else return( ERR_X509_CERT_INVALID_PEM );
00699
00700 buflen -= s2 - buf;
00701 buf = s2;
00702 }
00703 else
00704 {
00705
00706
00707
00708 p = (unsigned char *) malloc( len = buflen );
00709
00710 if( p == NULL )
00711 return( 1 );
00712
00713 memcpy( p, buf, buflen );
00714
00715 buflen = 0;
00716 }
00717
00718 crt->raw.p = p;
00719 crt->raw.len = len;
00720 end = p + len;
00721
00722
00723
00724
00725
00726
00727
00728 if( ( ret = asn1_get_tag( &p, end, &len,
00729 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
00730 {
00731 x509_free_cert( crt );
00732 return( ERR_X509_CERT_INVALID_FORMAT );
00733 }
00734
00735 if( len != (int) ( end - p ) )
00736 {
00737 x509_free_cert( crt );
00738 return( ERR_X509_CERT_INVALID_FORMAT |
00739 ERR_ASN1_LENGTH_MISMATCH );
00740 }
00741
00742
00743
00744
00745 crt->tbs.p = p;
00746
00747 if( ( ret = asn1_get_tag( &p, end, &len,
00748 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
00749 {
00750 x509_free_cert( crt );
00751 return( ERR_X509_CERT_INVALID_FORMAT | ret );
00752 }
00753
00754 end = p + len;
00755 crt->tbs.len = end - crt->tbs.p;
00756
00757
00758
00759
00760
00761
00762
00763
00764 if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 ||
00765 ( ret = x509_get_serial( &p, end, &crt->serial ) ) != 0 ||
00766 ( ret = x509_get_alg( &p, end, &crt->sig_oid1 ) ) != 0 )
00767 {
00768 x509_free_cert( crt );
00769 return( ret );
00770 }
00771
00772 crt->version++;
00773
00774 if( crt->version > 3 )
00775 {
00776 x509_free_cert( crt );
00777 return( ERR_X509_CERT_UNKNOWN_VERSION );
00778 }
00779
00780 if( crt->sig_oid1.len != 9 ||
00781 memcmp( crt->sig_oid1.p, OID_PKCS1, 8 ) != 0 )
00782 {
00783 x509_free_cert( crt );
00784 return( ERR_X509_CERT_UNKNOWN_SIG_ALG );
00785 }
00786
00787 if( crt->sig_oid1.p[8] < 2 ||
00788 crt->sig_oid1.p[8] > 5 )
00789 {
00790 x509_free_cert( crt );
00791 return( ERR_X509_CERT_UNKNOWN_SIG_ALG );
00792 }
00793
00794
00795
00796
00797 crt->issuer_raw.p = p;
00798
00799 if( ( ret = asn1_get_tag( &p, end, &len,
00800 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
00801 {
00802 x509_free_cert( crt );
00803 return( ERR_X509_CERT_INVALID_FORMAT | ret );
00804 }
00805
00806 if( ( ret = x509_get_name( &p, p + len, &crt->issuer ) ) != 0 )
00807 {
00808 x509_free_cert( crt );
00809 return( ret );
00810 }
00811
00812 crt->issuer_raw.len = p - crt->issuer_raw.p;
00813
00814
00815
00816
00817
00818
00819
00820 if( ( ret = x509_get_dates( &p, end, &crt->valid_from,
00821 &crt->valid_to ) ) != 0 )
00822 {
00823 x509_free_cert( crt );
00824 return( ret );
00825 }
00826
00827
00828
00829
00830 crt->subject_raw.p = p;
00831
00832 if( ( ret = asn1_get_tag( &p, end, &len,
00833 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
00834 {
00835 x509_free_cert( crt );
00836 return( ERR_X509_CERT_INVALID_FORMAT | ret );
00837 }
00838
00839 if( ( ret = x509_get_name( &p, p + len, &crt->subject ) ) != 0 )
00840 {
00841 x509_free_cert( crt );
00842 return( ret );
00843 }
00844
00845 crt->subject_raw.len = p - crt->subject_raw.p;
00846
00847
00848
00849
00850
00851
00852 if( ( ret = asn1_get_tag( &p, end, &len,
00853 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
00854 {
00855 x509_free_cert( crt );
00856 return( ERR_X509_CERT_INVALID_FORMAT | ret );
00857 }
00858
00859 if( ( ret = x509_get_pubkey( &p, p + len, &crt->pk_oid,
00860 &crt->rsa.N, &crt->rsa.E ) ) != 0 )
00861 {
00862 x509_free_cert( crt );
00863 return( ret );
00864 }
00865
00866 if( ( ret = rsa_check_pubkey( &crt->rsa ) ) != 0 )
00867 {
00868 x509_free_cert( crt );
00869 return( ret );
00870 }
00871
00872 crt->rsa.len = ( mpi_msb( &crt->rsa.N ) + 7 ) >> 3;
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882 if( crt->version == 2 || crt->version == 3 )
00883 {
00884 ret = x509_get_uid( &p, end, &crt->issuer_id, 1 );
00885 if( ret != 0 )
00886 {
00887 x509_free_cert( crt );
00888 return( ret );
00889 }
00890 }
00891
00892 if( crt->version == 2 || crt->version == 3 )
00893 {
00894 ret = x509_get_uid( &p, end, &crt->subject_id, 2 );
00895 if( ret != 0 )
00896 {
00897 x509_free_cert( crt );
00898 return( ret );
00899 }
00900 }
00901
00902 if( crt->version == 3 )
00903 {
00904 ret = x509_get_ext( &p, end, &crt->v3_ext,
00905 &crt->ca_istrue, &crt->max_pathlen );
00906 if( ret != 0 )
00907 {
00908 x509_free_cert( crt );
00909 return( ret );
00910 }
00911 }
00912
00913 if( p != end )
00914 {
00915 x509_free_cert( crt );
00916 return( ERR_X509_CERT_INVALID_FORMAT |
00917 ERR_ASN1_LENGTH_MISMATCH );
00918 }
00919
00920 end = crt->raw.p + crt->raw.len;
00921
00922
00923
00924
00925
00926 if( ( ret = x509_get_alg( &p, end, &crt->sig_oid2 ) ) != 0 )
00927 {
00928 x509_free_cert( crt );
00929 return( ret );
00930 }
00931
00932 if( memcmp( crt->sig_oid1.p, crt->sig_oid2.p, 9 ) != 0 )
00933 {
00934 x509_free_cert( crt );
00935 return( ERR_X509_CERT_SIG_MISMATCH );
00936 }
00937
00938 if( ( ret = x509_get_sig( &p, end, &crt->sig ) ) != 0 )
00939 {
00940 x509_free_cert( crt );
00941 return( ret );
00942 }
00943
00944 if( p != end )
00945 {
00946 x509_free_cert( crt );
00947 return( ERR_X509_CERT_INVALID_FORMAT |
00948 ERR_ASN1_LENGTH_MISMATCH );
00949 }
00950
00951 crt->next = (x509_cert *) malloc( sizeof( x509_cert ) );
00952
00953 if( crt->next == NULL )
00954 {
00955 x509_free_cert( crt );
00956 return( 1 );
00957 }
00958
00959 crt = crt->next;
00960 memset( crt, 0, sizeof( x509_cert ) );
00961
00962 if( buflen > 0 )
00963 return( x509_add_certs( crt, buf, buflen ) );
00964
00965 return( 0 );
00966 }
00967
00968
00969
00970
00971 int x509_read_crtfile( x509_cert *chain, char *path )
00972 {
00973 int ret;
00974 FILE *f;
00975 size_t n;
00976 unsigned char *buf;
00977
00978 if( ( f = fopen( path, "rb" ) ) == NULL )
00979 return( 1 );
00980
00981 fseek( f, 0, SEEK_END );
00982 n = (size_t) ftell( f );
00983 fseek( f, 0, SEEK_SET );
00984
00985 if( ( buf = (unsigned char *) malloc( n + 1 ) ) == NULL )
00986 return( 1 );
00987
00988 if( fread( buf, 1, n, f ) != n )
00989 {
00990 fclose( f );
00991 free( buf );
00992 return( 1 );
00993 }
00994
00995 buf[n] = '\0';
00996
00997 ret = x509_add_certs( chain, buf, (int) n );
00998
00999 memset( buf, 0, n + 1 );
01000 free( buf );
01001 fclose( f );
01002
01003 return( ret );
01004 }
01005
01006 #if !defined(NO_DES)
01007
01008
01009
01010 static int x509_des3_getiv( unsigned char *s, unsigned char iv[8] )
01011 {
01012 int i, j;
01013
01014 memset( iv, 0, 8 );
01015
01016 for( i = 0; i < 16; i++, s++ )
01017 {
01018 if( *s >= '0' && *s <= '9' ) j = *s - '0'; else
01019 if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else
01020 if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else
01021 return( ERR_X509_KEY_INVALID_ENC_IV );
01022
01023 if( (i & 1) != 0 )
01024 iv[i >> 1] |= j;
01025 else
01026 iv[i >> 1] |= j << 4;
01027 }
01028
01029 return( 0 );
01030 }
01031
01032
01033
01034
01035 static void x509_des3_decrypt( unsigned char des3_iv[8],
01036 unsigned char *buf, int buflen,
01037 unsigned char *pwd, int pwdlen )
01038 {
01039 md5_context md5_ctx;
01040 des3_context des3_ctx;
01041 unsigned char md5sum[16];
01042 unsigned char des3_key[24];
01043
01044
01045
01046
01047
01048 md5_starts( &md5_ctx );
01049 md5_update( &md5_ctx, pwd, pwdlen );
01050 md5_update( &md5_ctx, des3_iv, 8 );
01051 md5_finish( &md5_ctx, md5sum );
01052 memcpy( des3_key, md5sum, 16 );
01053
01054 md5_starts( &md5_ctx );
01055 md5_update( &md5_ctx, md5sum, 16 );
01056 md5_update( &md5_ctx, pwd, pwdlen );
01057 md5_update( &md5_ctx, des3_iv, 8 );
01058 md5_finish( &md5_ctx, md5sum );
01059 memcpy( des3_key + 16, md5sum, 8 );
01060
01061 des3_set_3keys( &des3_ctx, des3_key );
01062 des3_cbc_decrypt( &des3_ctx, des3_iv, buf, buf, buflen );
01063
01064 memset( & md5_ctx, 0, sizeof( md5_ctx ) );
01065 memset( &des3_ctx, 0, sizeof( des3_ctx ) );
01066 memset( md5sum, 0, 16 );
01067 memset( des3_key, 0, 24 );
01068 }
01069 #endif
01070
01071
01072
01073
01074 int x509_parse_key( rsa_context *rsa, unsigned char *buf, int buflen,
01075 unsigned char *pwd, int pwdlen )
01076 {
01077 int ret, len, enc;
01078 unsigned char *s1, *s2;
01079 unsigned char *p, *end;
01080 unsigned char des3_iv[8];
01081
01082 s1 = (unsigned char *) strstr( (char *) buf,
01083 "-----BEGIN RSA PRIVATE KEY-----" );
01084
01085 if( s1 != NULL )
01086 {
01087 s2 = (unsigned char *) strstr( (char *) buf,
01088 "-----END RSA PRIVATE KEY-----" );
01089
01090 if( s2 == NULL || s2 <= s1 )
01091 return( ERR_X509_KEY_INVALID_PEM );
01092
01093 s1 += 31;
01094 if( *s1 == '\r' ) s1++;
01095 if( *s1 == '\n' ) s1++;
01096 else return( ERR_X509_KEY_INVALID_PEM );
01097
01098 enc = 0;
01099
01100 if( memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 )
01101 {
01102 #if !defined(NO_DES)
01103 enc++;
01104
01105 s1 += 22;
01106 if( *s1 == '\r' ) s1++;
01107 if( *s1 == '\n' ) s1++;
01108 else return( ERR_X509_KEY_INVALID_PEM );
01109
01110 if( memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) != 0 )
01111 return( ERR_X509_KEY_UNKNOWN_ENC_ALG );
01112
01113 s1 += 23;
01114 if( x509_des3_getiv( s1, des3_iv ) != 0 )
01115 return( ERR_X509_KEY_INVALID_ENC_IV );
01116
01117 s1 += 16;
01118 if( *s1 == '\r' ) s1++;
01119 if( *s1 == '\n' ) s1++;
01120 else return( ERR_X509_KEY_INVALID_PEM );
01121 #else
01122 return( ERR_X509_FEATURE_UNAVAILABLE );
01123 #endif
01124 }
01125
01126 len = 0;
01127 ret = base64_decode( NULL, &len, s1, s2 - s1 );
01128
01129 if( ret == ERR_BASE64_INVALID_CHARACTER )
01130 return( ret | ERR_X509_KEY_INVALID_PEM );
01131
01132 if( ( buf = (unsigned char *) malloc( len ) ) == NULL )
01133 return( 1 );
01134
01135 if( ( ret = base64_decode( buf, &len, s1, s2 - s1 ) ) != 0 )
01136 {
01137 free( buf );
01138 return( ret | ERR_X509_KEY_INVALID_PEM );
01139 }
01140
01141 buflen = len;
01142
01143 #if !defined(NO_DES)
01144 if( enc != 0 )
01145 {
01146 if( pwd == NULL )
01147 {
01148 free( buf );
01149 return( ERR_X509_KEY_PASSWORD_REQUIRED );
01150 }
01151
01152 x509_des3_decrypt( des3_iv, buf, buflen, pwd, pwdlen );
01153
01154 if( buf[0] != 0x30 || buf[1] != 0x82 ||
01155 buf[4] != 0x02 || buf[5] != 0x01 )
01156 {
01157 free( buf );
01158 return( ERR_X509_KEY_PASSWORD_MISMATCH );
01159 }
01160 }
01161 #endif
01162 }
01163
01164 memset( rsa, 0, sizeof( rsa_context ) );
01165
01166 p = buf;
01167 end = buf + buflen;
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183 if( ( ret = asn1_get_tag( &p, end, &len,
01184 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
01185 {
01186 if( s1 != NULL )
01187 free( buf );
01188
01189 rsa_free( rsa );
01190 return( ERR_X509_KEY_INVALID_FORMAT | ret );
01191 }
01192
01193 end = p + len;
01194
01195 if( ( ret = asn1_get_int( &p, end, &rsa->ver ) ) != 0 )
01196 {
01197 if( s1 != NULL )
01198 free( buf );
01199
01200 rsa_free( rsa );
01201 return( ERR_X509_KEY_INVALID_FORMAT | ret );
01202 }
01203
01204 if( rsa->ver != 0 )
01205 {
01206 if( s1 != NULL )
01207 free( buf );
01208
01209 rsa_free( rsa );
01210 return( ret | ERR_X509_KEY_INVALID_VERSION );
01211 }
01212
01213 if( ( ret = asn1_get_mpi( &p, end, &rsa->N ) ) != 0 ||
01214 ( ret = asn1_get_mpi( &p, end, &rsa->E ) ) != 0 ||
01215 ( ret = asn1_get_mpi( &p, end, &rsa->D ) ) != 0 ||
01216 ( ret = asn1_get_mpi( &p, end, &rsa->P ) ) != 0 ||
01217 ( ret = asn1_get_mpi( &p, end, &rsa->Q ) ) != 0 ||
01218 ( ret = asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 ||
01219 ( ret = asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 ||
01220 ( ret = asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 )
01221 {
01222 if( s1 != NULL )
01223 free( buf );
01224
01225 rsa_free( rsa );
01226 return( ret | ERR_X509_KEY_INVALID_FORMAT );
01227 }
01228
01229 rsa->len = ( mpi_msb( &rsa->N ) + 7 ) >> 3;
01230
01231 if( p != end )
01232 {
01233 if( s1 != NULL )
01234 free( buf );
01235
01236 rsa_free( rsa );
01237 return( ERR_X509_KEY_INVALID_FORMAT |
01238 ERR_ASN1_LENGTH_MISMATCH );
01239 }
01240
01241 if( ( ret = rsa_check_privkey( rsa ) ) != 0 )
01242 {
01243 if( s1 != NULL )
01244 free( buf );
01245
01246 rsa_free( rsa );
01247 return( ret );
01248 }
01249
01250 if( s1 != NULL )
01251 free( buf );
01252
01253 return( 0 );
01254 }
01255
01256
01257
01258
01259 int x509_read_keyfile( rsa_context *rsa, char *path, char *pwd )
01260 {
01261 int ret;
01262 FILE *f;
01263 size_t n;
01264 unsigned char *buf;
01265
01266 if( ( f = fopen( path, "rb" ) ) == NULL )
01267 return( 1 );
01268
01269 fseek( f, 0, SEEK_END );
01270 n = (size_t) ftell( f );
01271 fseek( f, 0, SEEK_SET );
01272
01273 if( ( buf = (unsigned char *) malloc( n + 1 ) ) == NULL )
01274 return( 1 );
01275
01276 if( fread( buf, 1, n, f ) != n )
01277 {
01278 fclose( f );
01279 free( buf );
01280 return( 1 );
01281 }
01282
01283 buf[n] = '\0';
01284
01285 if( pwd == NULL )
01286 ret = x509_parse_key( rsa, buf, (int) n, NULL, 0 );
01287 else
01288 ret = x509_parse_key( rsa, buf, (int) n,
01289 (unsigned char *) pwd, strlen( pwd ) );
01290
01291 memset( buf, 0, n + 1 );
01292 free( buf );
01293 fclose( f );
01294
01295 return( ret );
01296 }
01297
01298 #if defined _MSC_VER && !defined snprintf
01299 #define snprintf _snprintf
01300 #endif
01301
01302
01303
01304
01305
01306 int x509_dn_gets( char *buf, char *end, x509_name *dn )
01307 {
01308 int i;
01309 unsigned char c;
01310 x509_name *name;
01311 char s[128], *p;
01312
01313 memset( s, 0, sizeof( s ) );
01314
01315 name = dn;
01316 p = buf;
01317
01318 while( name != NULL )
01319 {
01320 if( name != dn )
01321 p += snprintf( p, end - p, ", " );
01322
01323 if( memcmp( name->oid.p, OID_X520, 2 ) == 0 )
01324 {
01325 switch( name->oid.p[2] )
01326 {
01327 case X520_COMMON_NAME:
01328 p += snprintf( p, end - p, "CN=" ); break;
01329
01330 case X520_COUNTRY:
01331 p += snprintf( p, end - p, "C=" ); break;
01332
01333 case X520_LOCALITY:
01334 p += snprintf( p, end - p, "L=" ); break;
01335
01336 case X520_STATE:
01337 p += snprintf( p, end - p, "ST=" ); break;
01338
01339 case X520_ORGANIZATION:
01340 p += snprintf( p, end - p, "O=" ); break;
01341
01342 case X520_ORG_UNIT:
01343 p += snprintf( p, end - p, "OU=" ); break;
01344
01345 default:
01346 p += snprintf( p, end - p, "0x%02X=",
01347 name->oid.p[2] );
01348 break;
01349 }
01350 }
01351 else if( memcmp( name->oid.p, OID_PKCS9, 8 ) == 0 )
01352 {
01353 switch( name->oid.p[8] )
01354 {
01355 case PKCS9_EMAIL:
01356 p += snprintf( p, end - p, "emailAddress=" ); break;
01357
01358 default:
01359 p += snprintf( p, end - p, "0x%02X=",
01360 name->oid.p[8] );
01361 break;
01362 }
01363 }
01364 else
01365 p += snprintf( p, end - p, "\?\?=" );
01366
01367 for( i = 0; i < name->val.len; i++ )
01368 {
01369 if( i >= (int) sizeof( s ) - 1 )
01370 break;
01371
01372 c = name->val.p[i];
01373 if( c < 32 || c == 127 || ( c > 128 && c < 160 ) )
01374 s[i] = '?';
01375 else s[i] = c;
01376 }
01377 s[i] = '\0';
01378 p += snprintf( p, end - p, "%s", s );
01379 name = name->next;
01380 }
01381
01382 return( p - buf );
01383 }
01384
01385
01386
01387
01388
01389 char *x509_cert_info( x509_cert *crt )
01390 {
01391 int i, n;
01392 char *buf, *p, *end;
01393
01394 if( ( buf = (char *) malloc( 4096 ) ) == NULL )
01395 return( NULL );
01396
01397 memset( buf, 0, 4096 );
01398
01399 p = buf;
01400 end = buf + 4096 - 1;
01401
01402 p += snprintf( p, end - p, "Cert. version : %d\n", crt->version );
01403 p += snprintf( p, end - p, "Serial Number : " );
01404
01405 n = ( crt->serial.len <= 32 )
01406 ? crt->serial.len : 32;
01407
01408 for( i = 1; i < n; i++ )
01409 p += snprintf( p, end - p, "%02X%s",
01410 crt->serial.p[i], ( i < n - 1 ) ? ":" : "" );
01411
01412 p += snprintf( p, end - p, "\nIssuer name : " );
01413 p += x509_dn_gets( p, end, &crt->issuer );
01414
01415 p += snprintf( p, end - p, "\nSubject name : " );
01416 p += x509_dn_gets( p, end, &crt->subject );
01417
01418 p += snprintf( p, end - p, "\nIssued on : " \
01419 "%04d-%02d-%02d %02d:%02d:%02d",
01420 crt->valid_from.year, crt->valid_from.mon,
01421 crt->valid_from.day, crt->valid_from.hour,
01422 crt->valid_from.min, crt->valid_from.sec );
01423
01424 p += snprintf( p, end - p, "\nExpires on : " \
01425 "%04d-%02d-%02d %02d:%02d:%02d",
01426 crt->valid_to.year, crt->valid_to.mon,
01427 crt->valid_to.day, crt->valid_to.hour,
01428 crt->valid_to.min, crt->valid_to.sec );
01429
01430 p += snprintf( p, end - p, "\nSigned using : RSA+" );
01431
01432 switch( crt->sig_oid1.p[8] )
01433 {
01434 case RSA_MD2 : p += snprintf( p, end - p, "MD2" ); break;
01435 case RSA_MD4 : p += snprintf( p, end - p, "MD4" ); break;
01436 case RSA_MD5 : p += snprintf( p, end - p, "MD5" ); break;
01437 case RSA_SHA1: p += snprintf( p, end - p, "SHA1" ); break;
01438 default: p += snprintf( p, end - p, "???" ); break;
01439 }
01440
01441 p += snprintf( p, end - p, "\nRSA key size : %u bits\n",
01442 crt->rsa.N.n * (int) sizeof( unsigned long ) * 8 );
01443
01444 return( buf );
01445 }
01446
01447
01448
01449
01450 int x509_is_cert_expired( x509_cert *crt )
01451 {
01452 struct tm *lt;
01453 time_t tt;
01454
01455 tt = time( NULL );
01456 lt = localtime( &tt );
01457
01458 if( lt->tm_year > crt->valid_to.year - 1900 )
01459 return( BADCERT_HAS_EXPIRED );
01460
01461 if( lt->tm_year == crt->valid_to.year - 1900 &&
01462 lt->tm_mon > crt->valid_to.mon - 1 )
01463 return( BADCERT_HAS_EXPIRED );
01464
01465 if( lt->tm_year == crt->valid_to.year - 1900 &&
01466 lt->tm_mon == crt->valid_to.mon - 1 &&
01467 lt->tm_mday > crt->valid_to.day )
01468 return( BADCERT_HAS_EXPIRED );
01469
01470 return( 0 );
01471 }
01472
01473 static void x509_hash( unsigned char *in, int len, int alg,
01474 unsigned char *out )
01475 {
01476 switch( alg )
01477 {
01478 #if !defined(NO_MD2)
01479 case RSA_MD2 : md2( in, len, out ); break;
01480 #endif
01481 #if !defined(NO_MD4)
01482 case RSA_MD4 : md4( in, len, out ); break;
01483 #endif
01484 case RSA_MD5 : md5( in, len, out ); break;
01485 case RSA_SHA1 : sha1( in, len, out ); break;
01486 default:
01487 memset( out, '\xFF', len );
01488 break;
01489 }
01490 }
01491
01492
01493
01494
01495 int x509_verify_cert( x509_cert *crt, x509_cert *trust_ca,
01496 char *cn, int *flags )
01497 {
01498 int alg_id;
01499 int pathlen;
01500 x509_cert *cur;
01501 x509_name *name;
01502 unsigned char hash[20];
01503
01504 *flags = x509_is_cert_expired( crt );
01505
01506 if( cn != NULL )
01507 {
01508 name = &crt->subject;
01509
01510 while( name != NULL )
01511 {
01512 if( memcmp( name->oid.p, "\x55\x04\x03", 3 ) == 0 &&
01513 memcmp( name->val.p, cn, strlen( cn ) ) == 0 )
01514 break;
01515
01516 name = name->next;
01517 }
01518
01519 if( name == NULL )
01520 *flags |= BADCERT_CN_MISMATCH;
01521 }
01522
01523 *flags |= BADCERT_NOT_TRUSTED;
01524
01525
01526
01527
01528
01529 cur = crt->next;
01530
01531 pathlen = 1;
01532
01533 while( cur->version != 0 )
01534 {
01535 if( cur->ca_istrue == 0 ||
01536 crt->issuer_raw.len != cur->subject_raw.len ||
01537 memcmp( crt->issuer_raw.p, cur->subject_raw.p,
01538 crt->issuer_raw.len ) != 0 )
01539 {
01540 cur = cur->next;
01541 continue;
01542 }
01543
01544 alg_id = crt->sig_oid1.p[8];
01545
01546 x509_hash( crt->tbs.p, crt->tbs.len, alg_id, hash );
01547
01548 if( rsa_pkcs1_verify( &cur->rsa, alg_id, hash, 0,
01549 crt->sig.p, crt->sig.len ) != 0 )
01550 return( ERR_X509_SIG_VERIFY_FAILED );
01551
01552 pathlen++;
01553
01554 crt = cur;
01555 cur = crt->next;
01556 }
01557
01558
01559
01560
01561 while( trust_ca->version != 0 )
01562 {
01563 if( crt->issuer_raw.len != trust_ca->subject_raw.len ||
01564 memcmp( crt->issuer_raw.p, trust_ca->subject_raw.p,
01565 crt->issuer_raw.len ) != 0 )
01566 {
01567 trust_ca = trust_ca->next;
01568 continue;
01569 }
01570
01571 if( trust_ca->max_pathlen > 0 &&
01572 trust_ca->max_pathlen < pathlen )
01573 return( ERR_X509_SIG_VERIFY_FAILED );
01574
01575 alg_id = crt->sig_oid1.p[8];
01576
01577 x509_hash( crt->tbs.p, crt->tbs.len, alg_id, hash );
01578 if( rsa_pkcs1_verify( &trust_ca->rsa, alg_id, hash, 0,
01579 crt->sig.p, crt->sig.len ) != 0 )
01580 return( ERR_X509_SIG_VERIFY_FAILED );
01581
01582 break;
01583 }
01584
01585 if( trust_ca->version == 0 )
01586 return( ERR_X509_SIG_VERIFY_FAILED );
01587
01588 *flags &= ~BADCERT_NOT_TRUSTED;
01589
01590 return( 0 );
01591 }
01592
01593
01594
01595
01596 void x509_free_cert( x509_cert *crt )
01597 {
01598 x509_cert *cert_cur = crt;
01599 x509_cert *cert_prv;
01600 x509_name *name_cur;
01601 x509_name *name_prv;
01602
01603 if( crt == NULL )
01604 return;
01605
01606 do
01607 {
01608 rsa_free( &cert_cur->rsa );
01609
01610 name_cur = cert_cur->issuer.next;
01611 while( name_cur != NULL )
01612 {
01613 name_prv = name_cur;
01614 name_cur = name_cur->next;
01615 free( name_prv );
01616 }
01617
01618 name_cur = cert_cur->subject.next;
01619 while( name_cur != NULL )
01620 {
01621 name_prv = name_cur;
01622 name_cur = name_cur->next;
01623 free( name_prv );
01624 }
01625
01626 if( cert_cur->raw.p != NULL )
01627 free( cert_cur->raw.p );
01628
01629 cert_cur = cert_cur->next;
01630 }
01631 while( cert_cur != NULL );
01632
01633 cert_cur = crt;
01634 do
01635 {
01636 cert_prv = cert_cur;
01637 cert_cur = cert_cur->next;
01638
01639 if( cert_prv != crt )
01640 free( cert_prv );
01641 }
01642 while( cert_cur != NULL );
01643 }
01644
01645 static const char _x509_read_src[] = "_x509read_src";
01646
01647 #if defined(SELF_TEST)
01648
01649 #include "xyssl/certs.h"
01650
01651
01652
01653
01654 int x509_self_test( int verbose )
01655 {
01656 int ret, flags;
01657 x509_cert cacert;
01658 x509_cert clicert;
01659 rsa_context rsa;
01660
01661 if( verbose != 0 )
01662 printf( " X.509 certificate load: " );
01663
01664 memset( &clicert, 0, sizeof( x509_cert ) );
01665
01666 ret = x509_add_certs( &clicert, (unsigned char *) test_cli_crt,
01667 strlen( test_cli_crt ) );
01668 if( ret != 0 )
01669 {
01670 if( verbose != 0 )
01671 printf( "failed\n" );
01672
01673 return( ret );
01674 }
01675
01676 memset( &cacert, 0, sizeof( x509_cert ) );
01677
01678 ret = x509_add_certs( &cacert, (unsigned char *) test_ca_crt,
01679 strlen( test_ca_crt ) );
01680 if( ret != 0 )
01681 {
01682 if( verbose != 0 )
01683 printf( "failed\n" );
01684
01685 return( ret );
01686 }
01687
01688 if( verbose != 0 )
01689 printf( "passed\n X.509 private key load: " );
01690
01691 ret = x509_parse_key( &rsa,
01692 (unsigned char *) test_ca_key, strlen( test_ca_key ),
01693 (unsigned char *) test_ca_pwd, strlen( test_ca_pwd ) );
01694
01695 if( ret != 0 )
01696 {
01697 if( verbose != 0 )
01698 printf( "failed\n" );
01699
01700 return( ret );
01701 }
01702
01703 if( verbose != 0 )
01704 printf( "passed\n X.509 signature verify: ");
01705
01706 ret = x509_verify_cert( &clicert, &cacert, "Joe User", &flags );
01707 if( ret != 0 )
01708 {
01709 if( verbose != 0 )
01710 printf( "failed\n" );
01711
01712 return( ret );
01713 }
01714
01715 if( verbose != 0 )
01716 printf( "passed\n\n" );
01717
01718 x509_free_cert( &cacert );
01719 x509_free_cert( &clicert );
01720 rsa_free( &rsa );
01721
01722 return( 0 );
01723 }
01724 #else
01725 int x509_self_test( int verbose )
01726 {
01727 return( 0 );
01728 }
01729 #endif