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

Go to the documentation of this file.
00001 /*
00002  *  X.509 certificate and private key decoding
00003  *
00004  *  Copyright (C) 2006-2007  Christophe Devine
00005  *
00006  *  This library is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU Lesser General Public
00008  *  License, version 2.1 as published by the Free Software Foundation.
00009  *
00010  *  This library is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  *  Lesser General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU Lesser General Public
00016  *  License along with this library; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00018  *  MA  02110-1301  USA
00019  */
00020 /*
00021  *  The ITU-T X.509 standard defines a certificat format for PKI.
00022  *
00023  *  http://www.ietf.org/rfc/rfc2459.txt
00024  *  http://www.ietf.org/rfc/rfc3279.txt
00025  *
00026  *  ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
00027  *
00028  *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
00029  *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
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  * ASN.1 DER decoding routines
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  *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
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  *  CertificateSerialNumber  ::=  INTEGER
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  *  AlgorithmIdentifier  ::=  SEQUENCE  {
00231  *       algorithm               OBJECT IDENTIFIER,
00232  *       parameters              ANY DEFINED BY algorithm OPTIONAL  }
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      * assume the algorithm parameters must be NULL
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  *  RelativeDistinguishedName ::=
00271  *    SET OF AttributeTypeAndValue
00272  *
00273  *  AttributeTypeAndValue ::= SEQUENCE {
00274  *    type     AttributeType,
00275  *    value    AttributeValue }
00276  *
00277  *  AttributeType ::= OBJECT IDENTIFIER
00278  *
00279  *  AttributeValue ::= ANY DEFINED BY AttributeType
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      * recurse until end of SEQUENCE is reached
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  *  Validity ::= SEQUENCE {
00356  *       notBefore      Time,
00357  *       notAfter       Time }
00358  *
00359  *  Time ::= CHOICE {
00360  *       utcTime        UTCTime,
00361  *       generalTime    GeneralizedTime }
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      * TODO: also handle GeneralizedTime
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  *  SubjectPublicKeyInfo  ::=  SEQUENCE  {
00423  *       algorithm            AlgorithmIdentifier,
00424  *       subjectPublicKey     BIT STRING }
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      * only RSA public keys handled at this time
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      *  RSAPublicKey ::= SEQUENCE {
00458      *      modulus           INTEGER,  -- n
00459      *      publicExponent    INTEGER   -- e
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  * X.509 v2/v3 unique identifier (not parsed)
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  * X.509 v3 extensions (only BasicConstraints are parsed)
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      * Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
00565      *
00566      * Extension  ::=  SEQUENCE  {
00567      *      extnID      OBJECT IDENTIFIER,
00568      *      critical    BOOLEAN DEFAULT FALSE,
00569      *      extnValue   OCTET STRING  }
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          * BasicConstraints ::= SEQUENCE {
00603          *      cA                      BOOLEAN DEFAULT FALSE,
00604          *      pathLenConstraint       INTEGER (0..MAX) OPTIONAL }
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  * Parse one or more certificates and add them to the chain
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      * check if the certificate is encoded in base64
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          * get the DER data length and decode the buffer
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          * update the buffer size and offset
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          * nope, copy the raw DER data
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      * Certificate  ::=  SEQUENCE  {
00724      *      tbsCertificate       TBSCertificate,
00725      *      signatureAlgorithm   AlgorithmIdentifier,
00726      *      signatureValue       BIT STRING  }
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      * TBSCertificate  ::=  SEQUENCE  {
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      * Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
00759      *
00760      * CertificateSerialNumber  ::=  INTEGER
00761      *
00762      * signature            AlgorithmIdentifier
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      * issuer               Name
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      * Validity ::= SEQUENCE {
00816      *      notBefore      Time,
00817      *      notAfter       Time }
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      * subject              Name
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      * SubjectPublicKeyInfo  ::=  SEQUENCE
00849      *      algorithm            AlgorithmIdentifier,
00850      *      subjectPublicKey     BIT STRING  }
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      *  issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
00876      *                       -- If present, version shall be v2 or v3
00877      *  subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
00878      *                       -- If present, version shall be v2 or v3
00879      *  extensions      [3]  EXPLICIT Extensions OPTIONAL
00880      *                       -- If present, version shall be v3
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      *  signatureAlgorithm   AlgorithmIdentifier,
00924      *  signatureValue       BIT STRING
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  * Load one or more certificates and add them to the chain
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  * Read a 16-byte hex string and convert it to binary
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  * Decrypt with 3DES-CBC, using PBKDF1 for key derivation
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      * 3DES key[ 0..15] = MD5(pwd || IV)
01046      *      key[16..23] = MD5(pwd || IV || 3DES key[ 0..15])
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  * Parse a private RSA key
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      *  RSAPrivateKey ::= SEQUENCE {
01171      *      version           Version,
01172      *      modulus           INTEGER,  -- n
01173      *      publicExponent    INTEGER,  -- e
01174      *      privateExponent   INTEGER,  -- d
01175      *      prime1            INTEGER,  -- p
01176      *      prime2            INTEGER,  -- q
01177      *      exponent1         INTEGER,  -- d mod (p-1)
01178      *      exponent2         INTEGER,  -- d mod (q-1)
01179      *      coefficient       INTEGER,  -- (inverse of q) mod p
01180      *      otherPrimeInfos   OtherPrimeInfos OPTIONAL
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  * Load and parse a private RSA key
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  * Store the name in printable form into buf; no more
01304  * than (end - buf) characters will be written
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  * Return an informational string about the
01387  * certificate, or NULL if memory allocation failed
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  * Return 0 if the certificate is still valid, or BADCERT_HAS_EXPIRED
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  * Verify the certificate validity
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      * Iterate upwards in the given cert chain,
01527      * ignoring any upper cert with CA != TRUE.
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      * Atempt to validate topmost cert with our CA chain.
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  * Unallocate all certificate data
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  * Checkup routine
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

Generated on Fri May 16 14:49:55 2008 for Mobile-C by  doxygen 1.5.4