/home/dko/projects/mobilec/trunk/src/security/xyssl-0.7/library/x509read.c

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

Generated on Tue Jul 1 15:29:59 2008 for Mobile-C by  doxygen 1.5.4