Knight KE / Mbed OS Game_Master
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers x509_crt.c Source File

x509_crt.c

00001 /*
00002  *  X.509 certificate parsing and verification
00003  *
00004  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
00005  *  SPDX-License-Identifier: Apache-2.0
00006  *
00007  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
00008  *  not use this file except in compliance with the License.
00009  *  You may obtain a copy of the License at
00010  *
00011  *  http://www.apache.org/licenses/LICENSE-2.0
00012  *
00013  *  Unless required by applicable law or agreed to in writing, software
00014  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00015  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00016  *  See the License for the specific language governing permissions and
00017  *  limitations under the License.
00018  *
00019  *  This file is part of mbed TLS (https://tls.mbed.org)
00020  */
00021 /*
00022  *  The ITU-T X.509 standard defines a certificate format for PKI.
00023  *
00024  *  http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)
00025  *  http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
00026  *  http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
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  *  [SIRO] https://cabforum.org/wp-content/uploads/Chunghwatelecom201503cabforumV4.pdf
00032  */
00033 
00034 #if !defined(MBEDTLS_CONFIG_FILE)
00035 #include "mbedtls/config.h"
00036 #else
00037 #include MBEDTLS_CONFIG_FILE
00038 #endif
00039 
00040 #if defined(MBEDTLS_X509_CRT_PARSE_C)
00041 
00042 #include "mbedtls/x509_crt.h"
00043 #include "mbedtls/oid.h"
00044 #include "mbedtls/platform_util.h"
00045 
00046 #include <stdio.h>
00047 #include <string.h>
00048 
00049 #if defined(MBEDTLS_PEM_PARSE_C)
00050 #include "mbedtls/pem.h"
00051 #endif
00052 
00053 #if defined(MBEDTLS_PLATFORM_C)
00054 #include "mbedtls/platform.h"
00055 #else
00056 #include <stdlib.h>
00057 #define mbedtls_free       free
00058 #define mbedtls_calloc    calloc
00059 #define mbedtls_snprintf   snprintf
00060 #endif
00061 
00062 #if defined(MBEDTLS_THREADING_C)
00063 #include "mbedtls/threading.h"
00064 #endif
00065 
00066 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
00067 #include <windows.h>
00068 #else
00069 #include <time.h>
00070 #endif
00071 
00072 #if defined(MBEDTLS_FS_IO)
00073 #include <stdio.h>
00074 #if !defined(_WIN32) || defined(EFIX64) || defined(EFI32)
00075 #include <sys/types.h>
00076 #include <sys/stat.h>
00077 #include <dirent.h>
00078 #endif /* !_WIN32 || EFIX64 || EFI32 */
00079 #endif
00080 
00081 /*
00082  * Item in a verification chain: cert and flags for it
00083  */
00084 typedef struct {
00085     mbedtls_x509_crt *crt;
00086     uint32_t flags;
00087 } x509_crt_verify_chain_item;
00088 
00089 /*
00090  * Max size of verification chain: end-entity + intermediates + trusted root
00091  */
00092 #define X509_MAX_VERIFY_CHAIN_SIZE    ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 )
00093 
00094 /*
00095  * Default profile
00096  */
00097 const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default =
00098 {
00099 #if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES)
00100     /* Allow SHA-1 (weak, but still safe in controlled environments) */
00101     MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) |
00102 #endif
00103     /* Only SHA-2 hashes */
00104     MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) |
00105     MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
00106     MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
00107     MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
00108     0xFFFFFFF, /* Any PK alg    */
00109     0xFFFFFFF, /* Any curve     */
00110     2048,
00111 };
00112 
00113 /*
00114  * Next-default profile
00115  */
00116 const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next =
00117 {
00118     /* Hashes from SHA-256 and above */
00119     MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
00120     MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
00121     MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
00122     0xFFFFFFF, /* Any PK alg    */
00123 #if defined(MBEDTLS_ECP_C)
00124     /* Curves at or above 128-bit security level */
00125     MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) |
00126     MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ) |
00127     MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP521R1 ) |
00128     MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP256R1 ) |
00129     MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP384R1 ) |
00130     MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP512R1 ) |
00131     MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256K1 ),
00132 #else
00133     0,
00134 #endif
00135     2048,
00136 };
00137 
00138 /*
00139  * NSA Suite B Profile
00140  */
00141 const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb =
00142 {
00143     /* Only SHA-256 and 384 */
00144     MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
00145     MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ),
00146     /* Only ECDSA */
00147     MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ) |
00148     MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECKEY ),
00149 #if defined(MBEDTLS_ECP_C)
00150     /* Only NIST P-256 and P-384 */
00151     MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) |
00152     MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ),
00153 #else
00154     0,
00155 #endif
00156     0,
00157 };
00158 
00159 /*
00160  * Check md_alg against profile
00161  * Return 0 if md_alg is acceptable for this profile, -1 otherwise
00162  */
00163 static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile,
00164                                       mbedtls_md_type_t md_alg )
00165 {
00166     if( ( profile->allowed_mds & MBEDTLS_X509_ID_FLAG( md_alg ) ) != 0 )
00167         return( 0 );
00168 
00169     return( -1 );
00170 }
00171 
00172 /*
00173  * Check pk_alg against profile
00174  * Return 0 if pk_alg is acceptable for this profile, -1 otherwise
00175  */
00176 static int x509_profile_check_pk_alg( const mbedtls_x509_crt_profile *profile,
00177                                       mbedtls_pk_type_t pk_alg )
00178 {
00179     if( ( profile->allowed_pks & MBEDTLS_X509_ID_FLAG( pk_alg ) ) != 0 )
00180         return( 0 );
00181 
00182     return( -1 );
00183 }
00184 
00185 /*
00186  * Check key against profile
00187  * Return 0 if pk is acceptable for this profile, -1 otherwise
00188  */
00189 static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile,
00190                                    const mbedtls_pk_context *pk )
00191 {
00192     const mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type( pk );
00193 
00194 #if defined(MBEDTLS_RSA_C)
00195     if( pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS )
00196     {
00197         if( mbedtls_pk_get_bitlen( pk ) >= profile->rsa_min_bitlen )
00198             return( 0 );
00199 
00200         return( -1 );
00201     }
00202 #endif
00203 
00204 #if defined(MBEDTLS_ECP_C)
00205     if( pk_alg == MBEDTLS_PK_ECDSA ||
00206         pk_alg == MBEDTLS_PK_ECKEY ||
00207         pk_alg == MBEDTLS_PK_ECKEY_DH )
00208     {
00209         const mbedtls_ecp_group_id gid = mbedtls_pk_ec( *pk )->grp .id ;
00210 
00211         if( ( profile->allowed_curves & MBEDTLS_X509_ID_FLAG( gid ) ) != 0 )
00212             return( 0 );
00213 
00214         return( -1 );
00215     }
00216 #endif
00217 
00218     return( -1 );
00219 }
00220 
00221 /*
00222  *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
00223  */
00224 static int x509_get_version( unsigned char **p,
00225                              const unsigned char *end,
00226                              int *ver )
00227 {
00228     int ret;
00229     size_t len;
00230 
00231     if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
00232             MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) != 0 )
00233     {
00234         if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
00235         {
00236             *ver = 0;
00237             return( 0 );
00238         }
00239 
00240         return( ret );
00241     }
00242 
00243     end = *p + len;
00244 
00245     if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 )
00246         return( MBEDTLS_ERR_X509_INVALID_VERSION + ret );
00247 
00248     if( *p != end )
00249         return( MBEDTLS_ERR_X509_INVALID_VERSION +
00250                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
00251 
00252     return( 0 );
00253 }
00254 
00255 /*
00256  *  Validity ::= SEQUENCE {
00257  *       notBefore      Time,
00258  *       notAfter       Time }
00259  */
00260 static int x509_get_dates( unsigned char **p,
00261                            const unsigned char *end,
00262                            mbedtls_x509_time *from,
00263                            mbedtls_x509_time *to )
00264 {
00265     int ret;
00266     size_t len;
00267 
00268     if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
00269             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
00270         return( MBEDTLS_ERR_X509_INVALID_DATE + ret );
00271 
00272     end = *p + len;
00273 
00274     if( ( ret = mbedtls_x509_get_time( p, end, from ) ) != 0 )
00275         return( ret );
00276 
00277     if( ( ret = mbedtls_x509_get_time( p, end, to ) ) != 0 )
00278         return( ret );
00279 
00280     if( *p != end )
00281         return( MBEDTLS_ERR_X509_INVALID_DATE +
00282                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
00283 
00284     return( 0 );
00285 }
00286 
00287 /*
00288  * X.509 v2/v3 unique identifier (not parsed)
00289  */
00290 static int x509_get_uid( unsigned char **p,
00291                          const unsigned char *end,
00292                          mbedtls_x509_buf *uid, int n )
00293 {
00294     int ret;
00295 
00296     if( *p == end )
00297         return( 0 );
00298 
00299     uid->tag = **p;
00300 
00301     if( ( ret = mbedtls_asn1_get_tag( p, end, &uid->len,
00302             MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | n ) ) != 0 )
00303     {
00304         if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
00305             return( 0 );
00306 
00307         return( ret );
00308     }
00309 
00310     uid->p = *p;
00311     *p += uid->len;
00312 
00313     return( 0 );
00314 }
00315 
00316 static int x509_get_basic_constraints( unsigned char **p,
00317                                        const unsigned char *end,
00318                                        int *ca_istrue,
00319                                        int *max_pathlen )
00320 {
00321     int ret;
00322     size_t len;
00323 
00324     /*
00325      * BasicConstraints ::= SEQUENCE {
00326      *      cA                      BOOLEAN DEFAULT FALSE,
00327      *      pathLenConstraint       INTEGER (0..MAX) OPTIONAL }
00328      */
00329     *ca_istrue = 0; /* DEFAULT FALSE */
00330     *max_pathlen = 0; /* endless */
00331 
00332     if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
00333             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
00334         return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
00335 
00336     if( *p == end )
00337         return( 0 );
00338 
00339     if( ( ret = mbedtls_asn1_get_bool( p, end, ca_istrue ) ) != 0 )
00340     {
00341         if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
00342             ret = mbedtls_asn1_get_int( p, end, ca_istrue );
00343 
00344         if( ret != 0 )
00345             return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
00346 
00347         if( *ca_istrue != 0 )
00348             *ca_istrue = 1;
00349     }
00350 
00351     if( *p == end )
00352         return( 0 );
00353 
00354     if( ( ret = mbedtls_asn1_get_int( p, end, max_pathlen ) ) != 0 )
00355         return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
00356 
00357     if( *p != end )
00358         return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
00359                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
00360 
00361     (*max_pathlen)++;
00362 
00363     return( 0 );
00364 }
00365 
00366 static int x509_get_ns_cert_type( unsigned char **p,
00367                                        const unsigned char *end,
00368                                        unsigned char *ns_cert_type)
00369 {
00370     int ret;
00371     mbedtls_x509_bitstring bs = { 0, 0, NULL };
00372 
00373     if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 )
00374         return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
00375 
00376     if( bs.len != 1 )
00377         return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
00378                 MBEDTLS_ERR_ASN1_INVALID_LENGTH );
00379 
00380     /* Get actual bitstring */
00381     *ns_cert_type = *bs.p;
00382     return( 0 );
00383 }
00384 
00385 static int x509_get_key_usage( unsigned char **p,
00386                                const unsigned char *end,
00387                                unsigned int *key_usage)
00388 {
00389     int ret;
00390     size_t i;
00391     mbedtls_x509_bitstring bs = { 0, 0, NULL };
00392 
00393     if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 )
00394         return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
00395 
00396     if( bs.len < 1 )
00397         return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
00398                 MBEDTLS_ERR_ASN1_INVALID_LENGTH );
00399 
00400     /* Get actual bitstring */
00401     *key_usage = 0;
00402     for( i = 0; i < bs.len && i < sizeof( unsigned int ); i++ )
00403     {
00404         *key_usage |= (unsigned int) bs.p[i] << (8*i);
00405     }
00406 
00407     return( 0 );
00408 }
00409 
00410 /*
00411  * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
00412  *
00413  * KeyPurposeId ::= OBJECT IDENTIFIER
00414  */
00415 static int x509_get_ext_key_usage( unsigned char **p,
00416                                const unsigned char *end,
00417                                mbedtls_x509_sequence *ext_key_usage)
00418 {
00419     int ret;
00420 
00421     if( ( ret = mbedtls_asn1_get_sequence_of( p, end, ext_key_usage, MBEDTLS_ASN1_OID ) ) != 0 )
00422         return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
00423 
00424     /* Sequence length must be >= 1 */
00425     if( ext_key_usage->buf.p == NULL )
00426         return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
00427                 MBEDTLS_ERR_ASN1_INVALID_LENGTH );
00428 
00429     return( 0 );
00430 }
00431 
00432 /*
00433  * SubjectAltName ::= GeneralNames
00434  *
00435  * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
00436  *
00437  * GeneralName ::= CHOICE {
00438  *      otherName                       [0]     OtherName,
00439  *      rfc822Name                      [1]     IA5String,
00440  *      dNSName                         [2]     IA5String,
00441  *      x400Address                     [3]     ORAddress,
00442  *      directoryName                   [4]     Name,
00443  *      ediPartyName                    [5]     EDIPartyName,
00444  *      uniformResourceIdentifier       [6]     IA5String,
00445  *      iPAddress                       [7]     OCTET STRING,
00446  *      registeredID                    [8]     OBJECT IDENTIFIER }
00447  *
00448  * OtherName ::= SEQUENCE {
00449  *      type-id    OBJECT IDENTIFIER,
00450  *      value      [0] EXPLICIT ANY DEFINED BY type-id }
00451  *
00452  * EDIPartyName ::= SEQUENCE {
00453  *      nameAssigner            [0]     DirectoryString OPTIONAL,
00454  *      partyName               [1]     DirectoryString }
00455  *
00456  * NOTE: we only parse and use dNSName at this point.
00457  */
00458 static int x509_get_subject_alt_name( unsigned char **p,
00459                                       const unsigned char *end,
00460                                       mbedtls_x509_sequence *subject_alt_name )
00461 {
00462     int ret;
00463     size_t len, tag_len;
00464     mbedtls_asn1_buf *buf;
00465     unsigned char tag;
00466     mbedtls_asn1_sequence *cur = subject_alt_name;
00467 
00468     /* Get main sequence tag */
00469     if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
00470             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
00471         return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
00472 
00473     if( *p + len != end )
00474         return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
00475                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
00476 
00477     while( *p < end )
00478     {
00479         if( ( end - *p ) < 1 )
00480             return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
00481                     MBEDTLS_ERR_ASN1_OUT_OF_DATA );
00482 
00483         tag = **p;
00484         (*p)++;
00485         if( ( ret = mbedtls_asn1_get_len( p, end, &tag_len ) ) != 0 )
00486             return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
00487 
00488         if( ( tag & MBEDTLS_ASN1_TAG_CLASS_MASK ) !=
00489                 MBEDTLS_ASN1_CONTEXT_SPECIFIC )
00490         {
00491             return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
00492                     MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
00493         }
00494 
00495         /* Skip everything but DNS name */
00496         if( tag != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2 ) )
00497         {
00498             *p += tag_len;
00499             continue;
00500         }
00501 
00502         /* Allocate and assign next pointer */
00503         if( cur->buf.p != NULL )
00504         {
00505             if( cur->next != NULL )
00506                 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS );
00507 
00508             cur->next = mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) );
00509 
00510             if( cur->next == NULL )
00511                 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
00512                         MBEDTLS_ERR_ASN1_ALLOC_FAILED );
00513 
00514             cur = cur->next;
00515         }
00516 
00517         buf = &(cur->buf);
00518         buf->tag = tag;
00519         buf->p = *p;
00520         buf->len = tag_len;
00521         *p += buf->len;
00522     }
00523 
00524     /* Set final sequence entry's next pointer to NULL */
00525     cur->next = NULL;
00526 
00527     if( *p != end )
00528         return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
00529                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
00530 
00531     return( 0 );
00532 }
00533 
00534 /*
00535  * X.509 v3 extensions
00536  *
00537  */
00538 static int x509_get_crt_ext( unsigned char **p,
00539                              const unsigned char *end,
00540                              mbedtls_x509_crt *crt )
00541 {
00542     int ret;
00543     size_t len;
00544     unsigned char *end_ext_data, *end_ext_octet;
00545 
00546     if( ( ret = mbedtls_x509_get_ext( p, end, &crt->v3_ext, 3 ) ) != 0 )
00547     {
00548         if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
00549             return( 0 );
00550 
00551         return( ret );
00552     }
00553 
00554     while( *p < end )
00555     {
00556         /*
00557          * Extension  ::=  SEQUENCE  {
00558          *      extnID      OBJECT IDENTIFIER,
00559          *      critical    BOOLEAN DEFAULT FALSE,
00560          *      extnValue   OCTET STRING  }
00561          */
00562         mbedtls_x509_buf extn_oid = {0, 0, NULL};
00563         int is_critical = 0; /* DEFAULT FALSE */
00564         int ext_type = 0;
00565 
00566         if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
00567                 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
00568             return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
00569 
00570         end_ext_data = *p + len;
00571 
00572         /* Get extension ID */
00573         extn_oid.tag = **p;
00574 
00575         if( ( ret = mbedtls_asn1_get_tag( p, end, &extn_oid.len, MBEDTLS_ASN1_OID ) ) != 0 )
00576             return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
00577 
00578         extn_oid.p = *p;
00579         *p += extn_oid.len;
00580 
00581         if( ( end - *p ) < 1 )
00582             return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
00583                     MBEDTLS_ERR_ASN1_OUT_OF_DATA );
00584 
00585         /* Get optional critical */
00586         if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 &&
00587             ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) )
00588             return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
00589 
00590         /* Data should be octet string type */
00591         if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len,
00592                 MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
00593             return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
00594 
00595         end_ext_octet = *p + len;
00596 
00597         if( end_ext_octet != end_ext_data )
00598             return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
00599                     MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
00600 
00601         /*
00602          * Detect supported extensions
00603          */
00604         ret = mbedtls_oid_get_x509_ext_type( &extn_oid, &ext_type );
00605 
00606         if( ret != 0 )
00607         {
00608             /* No parser found, skip extension */
00609             *p = end_ext_octet;
00610 
00611 #if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
00612             if( is_critical )
00613             {
00614                 /* Data is marked as critical: fail */
00615                 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
00616                         MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
00617             }
00618 #endif
00619             continue;
00620         }
00621 
00622         /* Forbid repeated extensions */
00623         if( ( crt->ext_types & ext_type ) != 0 )
00624             return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS );
00625 
00626         crt->ext_types |= ext_type;
00627 
00628         switch( ext_type )
00629         {
00630         case MBEDTLS_X509_EXT_BASIC_CONSTRAINTS:
00631             /* Parse basic constraints */
00632             if( ( ret = x509_get_basic_constraints( p, end_ext_octet,
00633                     &crt->ca_istrue, &crt->max_pathlen ) ) != 0 )
00634                 return( ret );
00635             break;
00636 
00637         case MBEDTLS_X509_EXT_KEY_USAGE:
00638             /* Parse key usage */
00639             if( ( ret = x509_get_key_usage( p, end_ext_octet,
00640                     &crt->key_usage ) ) != 0 )
00641                 return( ret );
00642             break;
00643 
00644         case MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE:
00645             /* Parse extended key usage */
00646             if( ( ret = x509_get_ext_key_usage( p, end_ext_octet,
00647                     &crt->ext_key_usage ) ) != 0 )
00648                 return( ret );
00649             break;
00650 
00651         case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME:
00652             /* Parse subject alt name */
00653             if( ( ret = x509_get_subject_alt_name( p, end_ext_octet,
00654                     &crt->subject_alt_names ) ) != 0 )
00655                 return( ret );
00656             break;
00657 
00658         case MBEDTLS_X509_EXT_NS_CERT_TYPE:
00659             /* Parse netscape certificate type */
00660             if( ( ret = x509_get_ns_cert_type( p, end_ext_octet,
00661                     &crt->ns_cert_type ) ) != 0 )
00662                 return( ret );
00663             break;
00664 
00665         default:
00666             return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
00667         }
00668     }
00669 
00670     if( *p != end )
00671         return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
00672                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
00673 
00674     return( 0 );
00675 }
00676 
00677 /*
00678  * Parse and fill a single X.509 certificate in DER format
00679  */
00680 static int x509_crt_parse_der_core( mbedtls_x509_crt *crt, const unsigned char *buf,
00681                                     size_t buflen )
00682 {
00683     int ret;
00684     size_t len;
00685     unsigned char *p, *end, *crt_end;
00686     mbedtls_x509_buf sig_params1, sig_params2, sig_oid2;
00687 
00688     memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) );
00689     memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) );
00690     memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) );
00691 
00692     /*
00693      * Check for valid input
00694      */
00695     if( crt == NULL || buf == NULL )
00696         return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
00697 
00698     // Use the original buffer until we figure out actual length
00699     p = (unsigned char*) buf;
00700     len = buflen;
00701     end = p + len;
00702 
00703     /*
00704      * Certificate  ::=  SEQUENCE  {
00705      *      tbsCertificate       TBSCertificate,
00706      *      signatureAlgorithm   AlgorithmIdentifier,
00707      *      signatureValue       BIT STRING  }
00708      */
00709     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
00710             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
00711     {
00712         mbedtls_x509_crt_free( crt );
00713         return( MBEDTLS_ERR_X509_INVALID_FORMAT );
00714     }
00715 
00716     if( len > (size_t) ( end - p ) )
00717     {
00718         mbedtls_x509_crt_free( crt );
00719         return( MBEDTLS_ERR_X509_INVALID_FORMAT +
00720                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
00721     }
00722     crt_end = p + len;
00723 
00724     // Create and populate a new buffer for the raw field
00725     crt->raw.len = crt_end - buf;
00726     crt->raw.p = p = mbedtls_calloc( 1, crt->raw.len );
00727     if( p == NULL )
00728         return( MBEDTLS_ERR_X509_ALLOC_FAILED );
00729 
00730     memcpy( p, buf, crt->raw.len );
00731 
00732     // Direct pointers to the new buffer
00733     p += crt->raw.len - len;
00734     end = crt_end = p + len;
00735 
00736     /*
00737      * TBSCertificate  ::=  SEQUENCE  {
00738      */
00739     crt->tbs.p = p;
00740 
00741     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
00742             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
00743     {
00744         mbedtls_x509_crt_free( crt );
00745         return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
00746     }
00747 
00748     end = p + len;
00749     crt->tbs.len = end - crt->tbs.p;
00750 
00751     /*
00752      * Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
00753      *
00754      * CertificateSerialNumber  ::=  INTEGER
00755      *
00756      * signature            AlgorithmIdentifier
00757      */
00758     if( ( ret = x509_get_version(  &p, end, &crt->version  ) ) != 0 ||
00759         ( ret = mbedtls_x509_get_serial(   &p, end, &crt->serial   ) ) != 0 ||
00760         ( ret = mbedtls_x509_get_alg(      &p, end, &crt->sig_oid,
00761                                             &sig_params1 ) ) != 0 )
00762     {
00763         mbedtls_x509_crt_free( crt );
00764         return( ret );
00765     }
00766 
00767     if( crt->version < 0 || crt->version > 2 )
00768     {
00769         mbedtls_x509_crt_free( crt );
00770         return( MBEDTLS_ERR_X509_UNKNOWN_VERSION );
00771     }
00772 
00773     crt->version++;
00774 
00775     if( ( ret = mbedtls_x509_get_sig_alg( &crt->sig_oid, &sig_params1,
00776                                   &crt->sig_md, &crt->sig_pk,
00777                                   &crt->sig_opts ) ) != 0 )
00778     {
00779         mbedtls_x509_crt_free( crt );
00780         return( ret );
00781     }
00782 
00783     /*
00784      * issuer               Name
00785      */
00786     crt->issuer_raw.p = p;
00787 
00788     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
00789             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
00790     {
00791         mbedtls_x509_crt_free( crt );
00792         return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
00793     }
00794 
00795     if( ( ret = mbedtls_x509_get_name( &p, p + len, &crt->issuer ) ) != 0 )
00796     {
00797         mbedtls_x509_crt_free( crt );
00798         return( ret );
00799     }
00800 
00801     crt->issuer_raw.len = p - crt->issuer_raw.p;
00802 
00803     /*
00804      * Validity ::= SEQUENCE {
00805      *      notBefore      Time,
00806      *      notAfter       Time }
00807      *
00808      */
00809     if( ( ret = x509_get_dates( &p, end, &crt->valid_from,
00810                                          &crt->valid_to ) ) != 0 )
00811     {
00812         mbedtls_x509_crt_free( crt );
00813         return( ret );
00814     }
00815 
00816     /*
00817      * subject              Name
00818      */
00819     crt->subject_raw.p = p;
00820 
00821     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
00822             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
00823     {
00824         mbedtls_x509_crt_free( crt );
00825         return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
00826     }
00827 
00828     if( len && ( ret = mbedtls_x509_get_name( &p, p + len, &crt->subject ) ) != 0 )
00829     {
00830         mbedtls_x509_crt_free( crt );
00831         return( ret );
00832     }
00833 
00834     crt->subject_raw.len = p - crt->subject_raw.p;
00835 
00836     /*
00837      * SubjectPublicKeyInfo
00838      */
00839     if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &crt->pk ) ) != 0 )
00840     {
00841         mbedtls_x509_crt_free( crt );
00842         return( ret );
00843     }
00844 
00845     /*
00846      *  issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
00847      *                       -- If present, version shall be v2 or v3
00848      *  subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
00849      *                       -- If present, version shall be v2 or v3
00850      *  extensions      [3]  EXPLICIT Extensions OPTIONAL
00851      *                       -- If present, version shall be v3
00852      */
00853     if( crt->version == 2 || crt->version == 3 )
00854     {
00855         ret = x509_get_uid( &p, end, &crt->issuer_id,  1 );
00856         if( ret != 0 )
00857         {
00858             mbedtls_x509_crt_free( crt );
00859             return( ret );
00860         }
00861     }
00862 
00863     if( crt->version == 2 || crt->version == 3 )
00864     {
00865         ret = x509_get_uid( &p, end, &crt->subject_id,  2 );
00866         if( ret != 0 )
00867         {
00868             mbedtls_x509_crt_free( crt );
00869             return( ret );
00870         }
00871     }
00872 
00873 #if !defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3)
00874     if( crt->version == 3 )
00875 #endif
00876     {
00877         ret = x509_get_crt_ext( &p, end, crt );
00878         if( ret != 0 )
00879         {
00880             mbedtls_x509_crt_free( crt );
00881             return( ret );
00882         }
00883     }
00884 
00885     if( p != end )
00886     {
00887         mbedtls_x509_crt_free( crt );
00888         return( MBEDTLS_ERR_X509_INVALID_FORMAT +
00889                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
00890     }
00891 
00892     end = crt_end;
00893 
00894     /*
00895      *  }
00896      *  -- end of TBSCertificate
00897      *
00898      *  signatureAlgorithm   AlgorithmIdentifier,
00899      *  signatureValue       BIT STRING
00900      */
00901     if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 )
00902     {
00903         mbedtls_x509_crt_free( crt );
00904         return( ret );
00905     }
00906 
00907     if( crt->sig_oid.len != sig_oid2.len ||
00908         memcmp( crt->sig_oid.p, sig_oid2.p, crt->sig_oid.len ) != 0 ||
00909         sig_params1.len != sig_params2.len ||
00910         ( sig_params1.len != 0 &&
00911           memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) )
00912     {
00913         mbedtls_x509_crt_free( crt );
00914         return( MBEDTLS_ERR_X509_SIG_MISMATCH );
00915     }
00916 
00917     if( ( ret = mbedtls_x509_get_sig( &p, end, &crt->sig ) ) != 0 )
00918     {
00919         mbedtls_x509_crt_free( crt );
00920         return( ret );
00921     }
00922 
00923     if( p != end )
00924     {
00925         mbedtls_x509_crt_free( crt );
00926         return( MBEDTLS_ERR_X509_INVALID_FORMAT +
00927                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
00928     }
00929 
00930     return( 0 );
00931 }
00932 
00933 /*
00934  * Parse one X.509 certificate in DER format from a buffer and add them to a
00935  * chained list
00936  */
00937 int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *buf,
00938                         size_t buflen )
00939 {
00940     int ret;
00941     mbedtls_x509_crt *crt = chain, *prev = NULL;
00942 
00943     /*
00944      * Check for valid input
00945      */
00946     if( crt == NULL || buf == NULL )
00947         return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
00948 
00949     while( crt->version != 0 && crt->next != NULL )
00950     {
00951         prev = crt;
00952         crt = crt->next;
00953     }
00954 
00955     /*
00956      * Add new certificate on the end of the chain if needed.
00957      */
00958     if( crt->version != 0 && crt->next == NULL )
00959     {
00960         crt->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) );
00961 
00962         if( crt->next == NULL )
00963             return( MBEDTLS_ERR_X509_ALLOC_FAILED );
00964 
00965         prev = crt;
00966         mbedtls_x509_crt_init( crt->next );
00967         crt = crt->next;
00968     }
00969 
00970     if( ( ret = x509_crt_parse_der_core( crt, buf, buflen ) ) != 0 )
00971     {
00972         if( prev )
00973             prev->next = NULL;
00974 
00975         if( crt != chain )
00976             mbedtls_free( crt );
00977 
00978         return( ret );
00979     }
00980 
00981     return( 0 );
00982 }
00983 
00984 /*
00985  * Parse one or more PEM certificates from a buffer and add them to the chained
00986  * list
00987  */
00988 int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen )
00989 {
00990 #if defined(MBEDTLS_PEM_PARSE_C)
00991     int success = 0, first_error = 0, total_failed = 0;
00992     int buf_format = MBEDTLS_X509_FORMAT_DER;
00993 #endif
00994 
00995     /*
00996      * Check for valid input
00997      */
00998     if( chain == NULL || buf == NULL )
00999         return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
01000 
01001     /*
01002      * Determine buffer content. Buffer contains either one DER certificate or
01003      * one or more PEM certificates.
01004      */
01005 #if defined(MBEDTLS_PEM_PARSE_C)
01006     if( buflen != 0 && buf[buflen - 1] == '\0' &&
01007         strstr( (const char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL )
01008     {
01009         buf_format = MBEDTLS_X509_FORMAT_PEM;
01010     }
01011 
01012     if( buf_format == MBEDTLS_X509_FORMAT_DER )
01013         return mbedtls_x509_crt_parse_der( chain, buf, buflen );
01014 #else
01015     return mbedtls_x509_crt_parse_der( chain, buf, buflen );
01016 #endif
01017 
01018 #if defined(MBEDTLS_PEM_PARSE_C)
01019     if( buf_format == MBEDTLS_X509_FORMAT_PEM )
01020     {
01021         int ret;
01022         mbedtls_pem_context pem;
01023 
01024         /* 1 rather than 0 since the terminating NULL byte is counted in */
01025         while( buflen > 1 )
01026         {
01027             size_t use_len;
01028             mbedtls_pem_init( &pem );
01029 
01030             /* If we get there, we know the string is null-terminated */
01031             ret = mbedtls_pem_read_buffer( &pem,
01032                            "-----BEGIN CERTIFICATE-----",
01033                            "-----END CERTIFICATE-----",
01034                            buf, NULL, 0, &use_len );
01035 
01036             if( ret == 0 )
01037             {
01038                 /*
01039                  * Was PEM encoded
01040                  */
01041                 buflen -= use_len;
01042                 buf += use_len;
01043             }
01044             else if( ret == MBEDTLS_ERR_PEM_BAD_INPUT_DATA )
01045             {
01046                 return( ret );
01047             }
01048             else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
01049             {
01050                 mbedtls_pem_free( &pem );
01051 
01052                 /*
01053                  * PEM header and footer were found
01054                  */
01055                 buflen -= use_len;
01056                 buf += use_len;
01057 
01058                 if( first_error == 0 )
01059                     first_error = ret;
01060 
01061                 total_failed++;
01062                 continue;
01063             }
01064             else
01065                 break;
01066 
01067             ret = mbedtls_x509_crt_parse_der( chain, pem.buf , pem.buflen  );
01068 
01069             mbedtls_pem_free( &pem );
01070 
01071             if( ret != 0 )
01072             {
01073                 /*
01074                  * Quit parsing on a memory error
01075                  */
01076                 if( ret == MBEDTLS_ERR_X509_ALLOC_FAILED )
01077                     return( ret );
01078 
01079                 if( first_error == 0 )
01080                     first_error = ret;
01081 
01082                 total_failed++;
01083                 continue;
01084             }
01085 
01086             success = 1;
01087         }
01088     }
01089 
01090     if( success )
01091         return( total_failed );
01092     else if( first_error )
01093         return( first_error );
01094     else
01095         return( MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT );
01096 #endif /* MBEDTLS_PEM_PARSE_C */
01097 }
01098 
01099 #if defined(MBEDTLS_FS_IO)
01100 /*
01101  * Load one or more certificates and add them to the chained list
01102  */
01103 int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path )
01104 {
01105     int ret;
01106     size_t n;
01107     unsigned char *buf;
01108 
01109     if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 )
01110         return( ret );
01111 
01112     ret = mbedtls_x509_crt_parse( chain, buf, n );
01113 
01114     mbedtls_platform_zeroize( buf, n );
01115     mbedtls_free( buf );
01116 
01117     return( ret );
01118 }
01119 
01120 int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
01121 {
01122     int ret = 0;
01123 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
01124     int w_ret;
01125     WCHAR szDir[MAX_PATH];
01126     char filename[MAX_PATH];
01127     char *p;
01128     size_t len = strlen( path );
01129 
01130     WIN32_FIND_DATAW file_data;
01131     HANDLE hFind;
01132 
01133     if( len > MAX_PATH - 3 )
01134         return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
01135 
01136     memset( szDir, 0, sizeof(szDir) );
01137     memset( filename, 0, MAX_PATH );
01138     memcpy( filename, path, len );
01139     filename[len++] = '\\';
01140     p = filename + len;
01141     filename[len++] = '*';
01142 
01143     w_ret = MultiByteToWideChar( CP_ACP, 0, filename, (int)len, szDir,
01144                                  MAX_PATH - 3 );
01145     if( w_ret == 0 )
01146         return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
01147 
01148     hFind = FindFirstFileW( szDir, &file_data );
01149     if( hFind == INVALID_HANDLE_VALUE )
01150         return( MBEDTLS_ERR_X509_FILE_IO_ERROR );
01151 
01152     len = MAX_PATH - len;
01153     do
01154     {
01155         memset( p, 0, len );
01156 
01157         if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
01158             continue;
01159 
01160         w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName,
01161                                      lstrlenW( file_data.cFileName ),
01162                                      p, (int) len - 1,
01163                                      NULL, NULL );
01164         if( w_ret == 0 )
01165         {
01166             ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
01167             goto cleanup;
01168         }
01169 
01170         w_ret = mbedtls_x509_crt_parse_file( chain, filename );
01171         if( w_ret < 0 )
01172             ret++;
01173         else
01174             ret += w_ret;
01175     }
01176     while( FindNextFileW( hFind, &file_data ) != 0 );
01177 
01178     if( GetLastError() != ERROR_NO_MORE_FILES )
01179         ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
01180 
01181 cleanup:
01182     FindClose( hFind );
01183 #else /* _WIN32 */
01184     int t_ret;
01185     int snp_ret;
01186     struct stat sb;
01187     struct dirent *entry;
01188     char entry_name[MBEDTLS_X509_MAX_FILE_PATH_LEN];
01189     DIR *dir = opendir( path );
01190 
01191     if( dir == NULL )
01192         return( MBEDTLS_ERR_X509_FILE_IO_ERROR );
01193 
01194 #if defined(MBEDTLS_THREADING_C)
01195     if( ( ret = mbedtls_mutex_lock( &mbedtls_threading_readdir_mutex ) ) != 0 )
01196     {
01197         closedir( dir );
01198         return( ret );
01199     }
01200 #endif /* MBEDTLS_THREADING_C */
01201 
01202     while( ( entry = readdir( dir ) ) != NULL )
01203     {
01204         snp_ret = mbedtls_snprintf( entry_name, sizeof entry_name,
01205                                     "%s/%s", path, entry->d_name );
01206 
01207         if( snp_ret < 0 || (size_t)snp_ret >= sizeof entry_name )
01208         {
01209             ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
01210             goto cleanup;
01211         }
01212         else if( stat( entry_name, &sb ) == -1 )
01213         {
01214             ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
01215             goto cleanup;
01216         }
01217 
01218         if( !S_ISREG( sb.st_mode ) )
01219             continue;
01220 
01221         // Ignore parse errors
01222         //
01223         t_ret = mbedtls_x509_crt_parse_file( chain, entry_name );
01224         if( t_ret < 0 )
01225             ret++;
01226         else
01227             ret += t_ret;
01228     }
01229 
01230 cleanup:
01231     closedir( dir );
01232 
01233 #if defined(MBEDTLS_THREADING_C)
01234     if( mbedtls_mutex_unlock( &mbedtls_threading_readdir_mutex ) != 0 )
01235         ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR;
01236 #endif /* MBEDTLS_THREADING_C */
01237 
01238 #endif /* _WIN32 */
01239 
01240     return( ret );
01241 }
01242 #endif /* MBEDTLS_FS_IO */
01243 
01244 static int x509_info_subject_alt_name( char **buf, size_t *size,
01245                                        const mbedtls_x509_sequence *subject_alt_name )
01246 {
01247     size_t i;
01248     size_t n = *size;
01249     char *p = *buf;
01250     const mbedtls_x509_sequence *cur = subject_alt_name;
01251     const char *sep = "";
01252     size_t sep_len = 0;
01253 
01254     while( cur != NULL )
01255     {
01256         if( cur->buf.len + sep_len >= n )
01257         {
01258             *p = '\0';
01259             return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
01260         }
01261 
01262         n -= cur->buf.len + sep_len;
01263         for( i = 0; i < sep_len; i++ )
01264             *p++ = sep[i];
01265         for( i = 0; i < cur->buf.len; i++ )
01266             *p++ = cur->buf.p[i];
01267 
01268         sep = ", ";
01269         sep_len = 2;
01270 
01271         cur = cur->next;
01272     }
01273 
01274     *p = '\0';
01275 
01276     *size = n;
01277     *buf = p;
01278 
01279     return( 0 );
01280 }
01281 
01282 #define PRINT_ITEM(i)                           \
01283     {                                           \
01284         ret = mbedtls_snprintf( p, n, "%s" i, sep );    \
01285         MBEDTLS_X509_SAFE_SNPRINTF;                        \
01286         sep = ", ";                             \
01287     }
01288 
01289 #define CERT_TYPE(type,name)                    \
01290     if( ns_cert_type & type )                   \
01291         PRINT_ITEM( name );
01292 
01293 static int x509_info_cert_type( char **buf, size_t *size,
01294                                 unsigned char ns_cert_type )
01295 {
01296     int ret;
01297     size_t n = *size;
01298     char *p = *buf;
01299     const char *sep = "";
01300 
01301     CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT,         "SSL Client" );
01302     CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER,         "SSL Server" );
01303     CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL,              "Email" );
01304     CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING,     "Object Signing" );
01305     CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_RESERVED,           "Reserved" );
01306     CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CA,             "SSL CA" );
01307     CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA,           "Email CA" );
01308     CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA,  "Object Signing CA" );
01309 
01310     *size = n;
01311     *buf = p;
01312 
01313     return( 0 );
01314 }
01315 
01316 #define KEY_USAGE(code,name)    \
01317     if( key_usage & code )      \
01318         PRINT_ITEM( name );
01319 
01320 static int x509_info_key_usage( char **buf, size_t *size,
01321                                 unsigned int key_usage )
01322 {
01323     int ret;
01324     size_t n = *size;
01325     char *p = *buf;
01326     const char *sep = "";
01327 
01328     KEY_USAGE( MBEDTLS_X509_KU_DIGITAL_SIGNATURE,    "Digital Signature" );
01329     KEY_USAGE( MBEDTLS_X509_KU_NON_REPUDIATION,      "Non Repudiation" );
01330     KEY_USAGE( MBEDTLS_X509_KU_KEY_ENCIPHERMENT,     "Key Encipherment" );
01331     KEY_USAGE( MBEDTLS_X509_KU_DATA_ENCIPHERMENT,    "Data Encipherment" );
01332     KEY_USAGE( MBEDTLS_X509_KU_KEY_AGREEMENT,        "Key Agreement" );
01333     KEY_USAGE( MBEDTLS_X509_KU_KEY_CERT_SIGN,        "Key Cert Sign" );
01334     KEY_USAGE( MBEDTLS_X509_KU_CRL_SIGN,             "CRL Sign" );
01335     KEY_USAGE( MBEDTLS_X509_KU_ENCIPHER_ONLY,        "Encipher Only" );
01336     KEY_USAGE( MBEDTLS_X509_KU_DECIPHER_ONLY,        "Decipher Only" );
01337 
01338     *size = n;
01339     *buf = p;
01340 
01341     return( 0 );
01342 }
01343 
01344 static int x509_info_ext_key_usage( char **buf, size_t *size,
01345                                     const mbedtls_x509_sequence *extended_key_usage )
01346 {
01347     int ret;
01348     const char *desc;
01349     size_t n = *size;
01350     char *p = *buf;
01351     const mbedtls_x509_sequence *cur = extended_key_usage;
01352     const char *sep = "";
01353 
01354     while( cur != NULL )
01355     {
01356         if( mbedtls_oid_get_extended_key_usage( &cur->buf, &desc ) != 0 )
01357             desc = "???";
01358 
01359         ret = mbedtls_snprintf( p, n, "%s%s", sep, desc );
01360         MBEDTLS_X509_SAFE_SNPRINTF;
01361 
01362         sep = ", ";
01363 
01364         cur = cur->next;
01365     }
01366 
01367     *size = n;
01368     *buf = p;
01369 
01370     return( 0 );
01371 }
01372 
01373 /*
01374  * Return an informational string about the certificate.
01375  */
01376 #define BEFORE_COLON    18
01377 #define BC              "18"
01378 int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix,
01379                    const mbedtls_x509_crt *crt )
01380 {
01381     int ret;
01382     size_t n;
01383     char *p;
01384     char key_size_str[BEFORE_COLON];
01385 
01386     p = buf;
01387     n = size;
01388 
01389     if( NULL == crt )
01390     {
01391         ret = mbedtls_snprintf( p, n, "\nCertificate is uninitialised!\n" );
01392         MBEDTLS_X509_SAFE_SNPRINTF;
01393 
01394         return( (int) ( size - n ) );
01395     }
01396 
01397     ret = mbedtls_snprintf( p, n, "%scert. version     : %d\n",
01398                                prefix, crt->version );
01399     MBEDTLS_X509_SAFE_SNPRINTF;
01400     ret = mbedtls_snprintf( p, n, "%sserial number     : ",
01401                                prefix );
01402     MBEDTLS_X509_SAFE_SNPRINTF;
01403 
01404     ret = mbedtls_x509_serial_gets( p, n, &crt->serial );
01405     MBEDTLS_X509_SAFE_SNPRINTF;
01406 
01407     ret = mbedtls_snprintf( p, n, "\n%sissuer name       : ", prefix );
01408     MBEDTLS_X509_SAFE_SNPRINTF;
01409     ret = mbedtls_x509_dn_gets( p, n, &crt->issuer  );
01410     MBEDTLS_X509_SAFE_SNPRINTF;
01411 
01412     ret = mbedtls_snprintf( p, n, "\n%ssubject name      : ", prefix );
01413     MBEDTLS_X509_SAFE_SNPRINTF;
01414     ret = mbedtls_x509_dn_gets( p, n, &crt->subject );
01415     MBEDTLS_X509_SAFE_SNPRINTF;
01416 
01417     ret = mbedtls_snprintf( p, n, "\n%sissued  on        : " \
01418                    "%04d-%02d-%02d %02d:%02d:%02d", prefix,
01419                    crt->valid_from.year, crt->valid_from.mon,
01420                    crt->valid_from.day,  crt->valid_from.hour,
01421                    crt->valid_from.min,  crt->valid_from.sec );
01422     MBEDTLS_X509_SAFE_SNPRINTF;
01423 
01424     ret = mbedtls_snprintf( p, n, "\n%sexpires on        : " \
01425                    "%04d-%02d-%02d %02d:%02d:%02d", prefix,
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     MBEDTLS_X509_SAFE_SNPRINTF;
01430 
01431     ret = mbedtls_snprintf( p, n, "\n%ssigned using      : ", prefix );
01432     MBEDTLS_X509_SAFE_SNPRINTF;
01433 
01434     ret = mbedtls_x509_sig_alg_gets( p, n, &crt->sig_oid, crt->sig_pk,
01435                              crt->sig_md, crt->sig_opts );
01436     MBEDTLS_X509_SAFE_SNPRINTF;
01437 
01438     /* Key size */
01439     if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON,
01440                                       mbedtls_pk_get_name( &crt->pk ) ) ) != 0 )
01441     {
01442         return( ret );
01443     }
01444 
01445     ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str,
01446                           (int) mbedtls_pk_get_bitlen( &crt->pk ) );
01447     MBEDTLS_X509_SAFE_SNPRINTF;
01448 
01449     /*
01450      * Optional extensions
01451      */
01452 
01453     if( crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS )
01454     {
01455         ret = mbedtls_snprintf( p, n, "\n%sbasic constraints : CA=%s", prefix,
01456                         crt->ca_istrue ? "true" : "false" );
01457         MBEDTLS_X509_SAFE_SNPRINTF;
01458 
01459         if( crt->max_pathlen > 0 )
01460         {
01461             ret = mbedtls_snprintf( p, n, ", max_pathlen=%d", crt->max_pathlen - 1 );
01462             MBEDTLS_X509_SAFE_SNPRINTF;
01463         }
01464     }
01465 
01466     if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
01467     {
01468         ret = mbedtls_snprintf( p, n, "\n%ssubject alt name  : ", prefix );
01469         MBEDTLS_X509_SAFE_SNPRINTF;
01470 
01471         if( ( ret = x509_info_subject_alt_name( &p, &n,
01472                                             &crt->subject_alt_names ) ) != 0 )
01473             return( ret );
01474     }
01475 
01476     if( crt->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE )
01477     {
01478         ret = mbedtls_snprintf( p, n, "\n%scert. type        : ", prefix );
01479         MBEDTLS_X509_SAFE_SNPRINTF;
01480 
01481         if( ( ret = x509_info_cert_type( &p, &n, crt->ns_cert_type ) ) != 0 )
01482             return( ret );
01483     }
01484 
01485     if( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE )
01486     {
01487         ret = mbedtls_snprintf( p, n, "\n%skey usage         : ", prefix );
01488         MBEDTLS_X509_SAFE_SNPRINTF;
01489 
01490         if( ( ret = x509_info_key_usage( &p, &n, crt->key_usage ) ) != 0 )
01491             return( ret );
01492     }
01493 
01494     if( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE )
01495     {
01496         ret = mbedtls_snprintf( p, n, "\n%sext key usage     : ", prefix );
01497         MBEDTLS_X509_SAFE_SNPRINTF;
01498 
01499         if( ( ret = x509_info_ext_key_usage( &p, &n,
01500                                              &crt->ext_key_usage ) ) != 0 )
01501             return( ret );
01502     }
01503 
01504     ret = mbedtls_snprintf( p, n, "\n" );
01505     MBEDTLS_X509_SAFE_SNPRINTF;
01506 
01507     return( (int) ( size - n ) );
01508 }
01509 
01510 struct x509_crt_verify_string {
01511     int code;
01512     const char *string;
01513 };
01514 
01515 static const struct x509_crt_verify_string x509_crt_verify_strings[] = {
01516     { MBEDTLS_X509_BADCERT_EXPIRED,       "The certificate validity has expired" },
01517     { MBEDTLS_X509_BADCERT_REVOKED,       "The certificate has been revoked (is on a CRL)" },
01518     { MBEDTLS_X509_BADCERT_CN_MISMATCH,   "The certificate Common Name (CN) does not match with the expected CN" },
01519     { MBEDTLS_X509_BADCERT_NOT_TRUSTED,   "The certificate is not correctly signed by the trusted CA" },
01520     { MBEDTLS_X509_BADCRL_NOT_TRUSTED,    "The CRL is not correctly signed by the trusted CA" },
01521     { MBEDTLS_X509_BADCRL_EXPIRED,        "The CRL is expired" },
01522     { MBEDTLS_X509_BADCERT_MISSING,       "Certificate was missing" },
01523     { MBEDTLS_X509_BADCERT_SKIP_VERIFY,   "Certificate verification was skipped" },
01524     { MBEDTLS_X509_BADCERT_OTHER,         "Other reason (can be used by verify callback)" },
01525     { MBEDTLS_X509_BADCERT_FUTURE,        "The certificate validity starts in the future" },
01526     { MBEDTLS_X509_BADCRL_FUTURE,         "The CRL is from the future" },
01527     { MBEDTLS_X509_BADCERT_KEY_USAGE,     "Usage does not match the keyUsage extension" },
01528     { MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, "Usage does not match the extendedKeyUsage extension" },
01529     { MBEDTLS_X509_BADCERT_NS_CERT_TYPE,  "Usage does not match the nsCertType extension" },
01530     { MBEDTLS_X509_BADCERT_BAD_MD,        "The certificate is signed with an unacceptable hash." },
01531     { MBEDTLS_X509_BADCERT_BAD_PK,        "The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA)." },
01532     { MBEDTLS_X509_BADCERT_BAD_KEY,       "The certificate is signed with an unacceptable key (eg bad curve, RSA too short)." },
01533     { MBEDTLS_X509_BADCRL_BAD_MD,         "The CRL is signed with an unacceptable hash." },
01534     { MBEDTLS_X509_BADCRL_BAD_PK,         "The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA)." },
01535     { MBEDTLS_X509_BADCRL_BAD_KEY,        "The CRL is signed with an unacceptable key (eg bad curve, RSA too short)." },
01536     { 0, NULL }
01537 };
01538 
01539 int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix,
01540                           uint32_t flags )
01541 {
01542     int ret;
01543     const struct x509_crt_verify_string *cur;
01544     char *p = buf;
01545     size_t n = size;
01546 
01547     for( cur = x509_crt_verify_strings; cur->string != NULL ; cur++ )
01548     {
01549         if( ( flags & cur->code ) == 0 )
01550             continue;
01551 
01552         ret = mbedtls_snprintf( p, n, "%s%s\n", prefix, cur->string );
01553         MBEDTLS_X509_SAFE_SNPRINTF;
01554         flags ^= cur->code;
01555     }
01556 
01557     if( flags != 0 )
01558     {
01559         ret = mbedtls_snprintf( p, n, "%sUnknown reason "
01560                                        "(this should not happen)\n", prefix );
01561         MBEDTLS_X509_SAFE_SNPRINTF;
01562     }
01563 
01564     return( (int) ( size - n ) );
01565 }
01566 
01567 #if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
01568 int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt,
01569                                       unsigned int usage )
01570 {
01571     unsigned int usage_must, usage_may;
01572     unsigned int may_mask = MBEDTLS_X509_KU_ENCIPHER_ONLY
01573                           | MBEDTLS_X509_KU_DECIPHER_ONLY;
01574 
01575     if( ( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) == 0 )
01576         return( 0 );
01577 
01578     usage_must = usage & ~may_mask;
01579 
01580     if( ( ( crt->key_usage & ~may_mask ) & usage_must ) != usage_must )
01581         return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
01582 
01583     usage_may = usage & may_mask;
01584 
01585     if( ( ( crt->key_usage & may_mask ) | usage_may ) != usage_may )
01586         return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
01587 
01588     return( 0 );
01589 }
01590 #endif
01591 
01592 #if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE)
01593 int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt,
01594                                        const char *usage_oid,
01595                                        size_t usage_len )
01596 {
01597     const mbedtls_x509_sequence *cur;
01598 
01599     /* Extension is not mandatory, absent means no restriction */
01600     if( ( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) == 0 )
01601         return( 0 );
01602 
01603     /*
01604      * Look for the requested usage (or wildcard ANY) in our list
01605      */
01606     for( cur = &crt->ext_key_usage; cur != NULL; cur = cur->next )
01607     {
01608         const mbedtls_x509_buf *cur_oid = &cur->buf;
01609 
01610         if( cur_oid->len == usage_len &&
01611             memcmp( cur_oid->p, usage_oid, usage_len ) == 0 )
01612         {
01613             return( 0 );
01614         }
01615 
01616         if( MBEDTLS_OID_CMP( MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE, cur_oid ) == 0 )
01617             return( 0 );
01618     }
01619 
01620     return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
01621 }
01622 #endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */
01623 
01624 #if defined(MBEDTLS_X509_CRL_PARSE_C)
01625 /*
01626  * Return 1 if the certificate is revoked, or 0 otherwise.
01627  */
01628 int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl )
01629 {
01630     const mbedtls_x509_crl_entry *cur = &crl->entry;
01631 
01632     while( cur != NULL && cur->serial.len != 0 )
01633     {
01634         if( crt->serial.len == cur->serial.len &&
01635             memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 )
01636         {
01637             if( mbedtls_x509_time_is_past( &cur->revocation_date ) )
01638                 return( 1 );
01639         }
01640 
01641         cur = cur->next;
01642     }
01643 
01644     return( 0 );
01645 }
01646 
01647 /*
01648  * Check that the given certificate is not revoked according to the CRL.
01649  * Skip validation if no CRL for the given CA is present.
01650  */
01651 static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca,
01652                                mbedtls_x509_crl *crl_list,
01653                                const mbedtls_x509_crt_profile *profile )
01654 {
01655     int flags = 0;
01656     unsigned char hash[MBEDTLS_MD_MAX_SIZE];
01657     const mbedtls_md_info_t *md_info;
01658 
01659     if( ca == NULL )
01660         return( flags );
01661 
01662     while( crl_list != NULL )
01663     {
01664         if( crl_list->version == 0 ||
01665             crl_list->issuer_raw.len != ca->subject_raw.len ||
01666             memcmp( crl_list->issuer_raw.p, ca->subject_raw.p,
01667                     crl_list->issuer_raw.len ) != 0 )
01668         {
01669             crl_list = crl_list->next;
01670             continue;
01671         }
01672 
01673         /*
01674          * Check if the CA is configured to sign CRLs
01675          */
01676 #if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
01677         if( mbedtls_x509_crt_check_key_usage( ca, MBEDTLS_X509_KU_CRL_SIGN ) != 0 )
01678         {
01679             flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
01680             break;
01681         }
01682 #endif
01683 
01684         /*
01685          * Check if CRL is correctly signed by the trusted CA
01686          */
01687         if( x509_profile_check_md_alg( profile, crl_list->sig_md ) != 0 )
01688             flags |= MBEDTLS_X509_BADCRL_BAD_MD;
01689 
01690         if( x509_profile_check_pk_alg( profile, crl_list->sig_pk ) != 0 )
01691             flags |= MBEDTLS_X509_BADCRL_BAD_PK;
01692 
01693         md_info = mbedtls_md_info_from_type( crl_list->sig_md );
01694         if( mbedtls_md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ) != 0 )
01695         {
01696             /* Note: this can't happen except after an internal error */
01697             flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
01698             break;
01699         }
01700 
01701         if( x509_profile_check_key( profile, &ca->pk ) != 0 )
01702             flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
01703 
01704         if( mbedtls_pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, &ca->pk,
01705                            crl_list->sig_md, hash, mbedtls_md_get_size( md_info ),
01706                            crl_list->sig.p, crl_list->sig.len ) != 0 )
01707         {
01708             flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
01709             break;
01710         }
01711 
01712         /*
01713          * Check for validity of CRL (Do not drop out)
01714          */
01715         if( mbedtls_x509_time_is_past( &crl_list->next_update ) )
01716             flags |= MBEDTLS_X509_BADCRL_EXPIRED;
01717 
01718         if( mbedtls_x509_time_is_future( &crl_list->this_update ) )
01719             flags |= MBEDTLS_X509_BADCRL_FUTURE;
01720 
01721         /*
01722          * Check if certificate is revoked
01723          */
01724         if( mbedtls_x509_crt_is_revoked( crt, crl_list ) )
01725         {
01726             flags |= MBEDTLS_X509_BADCERT_REVOKED;
01727             break;
01728         }
01729 
01730         crl_list = crl_list->next;
01731     }
01732 
01733     return( flags );
01734 }
01735 #endif /* MBEDTLS_X509_CRL_PARSE_C */
01736 
01737 /*
01738  * Like memcmp, but case-insensitive and always returns -1 if different
01739  */
01740 static int x509_memcasecmp( const void *s1, const void *s2, size_t len )
01741 {
01742     size_t i;
01743     unsigned char diff;
01744     const unsigned char *n1 = s1, *n2 = s2;
01745 
01746     for( i = 0; i < len; i++ )
01747     {
01748         diff = n1[i] ^ n2[i];
01749 
01750         if( diff == 0 )
01751             continue;
01752 
01753         if( diff == 32 &&
01754             ( ( n1[i] >= 'a' && n1[i] <= 'z' ) ||
01755               ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) )
01756         {
01757             continue;
01758         }
01759 
01760         return( -1 );
01761     }
01762 
01763     return( 0 );
01764 }
01765 
01766 /*
01767  * Return 0 if name matches wildcard, -1 otherwise
01768  */
01769 static int x509_check_wildcard( const char *cn, const mbedtls_x509_buf *name )
01770 {
01771     size_t i;
01772     size_t cn_idx = 0, cn_len = strlen( cn );
01773 
01774     /* We can't have a match if there is no wildcard to match */
01775     if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' )
01776         return( -1 );
01777 
01778     for( i = 0; i < cn_len; ++i )
01779     {
01780         if( cn[i] == '.' )
01781         {
01782             cn_idx = i;
01783             break;
01784         }
01785     }
01786 
01787     if( cn_idx == 0 )
01788         return( -1 );
01789 
01790     if( cn_len - cn_idx == name->len - 1 &&
01791         x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 )
01792     {
01793         return( 0 );
01794     }
01795 
01796     return( -1 );
01797 }
01798 
01799 /*
01800  * Compare two X.509 strings, case-insensitive, and allowing for some encoding
01801  * variations (but not all).
01802  *
01803  * Return 0 if equal, -1 otherwise.
01804  */
01805 static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b )
01806 {
01807     if( a->tag == b->tag &&
01808         a->len == b->len &&
01809         memcmp( a->p, b->p, b->len ) == 0 )
01810     {
01811         return( 0 );
01812     }
01813 
01814     if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
01815         ( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
01816         a->len == b->len &&
01817         x509_memcasecmp( a->p, b->p, b->len ) == 0 )
01818     {
01819         return( 0 );
01820     }
01821 
01822     return( -1 );
01823 }
01824 
01825 /*
01826  * Compare two X.509 Names (aka rdnSequence).
01827  *
01828  * See RFC 5280 section 7.1, though we don't implement the whole algorithm:
01829  * we sometimes return unequal when the full algorithm would return equal,
01830  * but never the other way. (In particular, we don't do Unicode normalisation
01831  * or space folding.)
01832  *
01833  * Return 0 if equal, -1 otherwise.
01834  */
01835 static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b )
01836 {
01837     /* Avoid recursion, it might not be optimised by the compiler */
01838     while( a != NULL || b != NULL )
01839     {
01840         if( a == NULL || b == NULL )
01841             return( -1 );
01842 
01843         /* type */
01844         if( a->oid.tag != b->oid.tag ||
01845             a->oid.len != b->oid.len ||
01846             memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 )
01847         {
01848             return( -1 );
01849         }
01850 
01851         /* value */
01852         if( x509_string_cmp( &a->val, &b->val ) != 0 )
01853             return( -1 );
01854 
01855         /* structure of the list of sets */
01856         if( a->next_merged != b->next_merged )
01857             return( -1 );
01858 
01859         a = a->next;
01860         b = b->next;
01861     }
01862 
01863     /* a == NULL == b */
01864     return( 0 );
01865 }
01866 
01867 /*
01868  * Check the signature of a certificate by its parent
01869  */
01870 static int x509_crt_check_signature( const mbedtls_x509_crt *child,
01871                                      mbedtls_x509_crt *parent )
01872 {
01873     const mbedtls_md_info_t *md_info;
01874     unsigned char hash[MBEDTLS_MD_MAX_SIZE];
01875 
01876     md_info = mbedtls_md_info_from_type( child->sig_md );
01877     if( mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ) != 0 )
01878     {
01879         /* Note: this can't happen except after an internal error */
01880         return( -1 );
01881     }
01882 
01883     if( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk,
01884                 child->sig_md, hash, mbedtls_md_get_size( md_info ),
01885                 child->sig.p, child->sig.len ) != 0 )
01886     {
01887         return( -1 );
01888     }
01889 
01890     return( 0 );
01891 }
01892 
01893 /*
01894  * Check if 'parent' is a suitable parent (signing CA) for 'child'.
01895  * Return 0 if yes, -1 if not.
01896  *
01897  * top means parent is a locally-trusted certificate
01898  */
01899 static int x509_crt_check_parent( const mbedtls_x509_crt *child,
01900                                   const mbedtls_x509_crt *parent,
01901                                   int top )
01902 {
01903     int need_ca_bit;
01904 
01905     /* Parent must be the issuer */
01906     if( x509_name_cmp( &child->issuer, &parent->subject ) != 0 )
01907         return( -1 );
01908 
01909     /* Parent must have the basicConstraints CA bit set as a general rule */
01910     need_ca_bit = 1;
01911 
01912     /* Exception: v1/v2 certificates that are locally trusted. */
01913     if( top && parent->version < 3 )
01914         need_ca_bit = 0;
01915 
01916     if( need_ca_bit && ! parent->ca_istrue )
01917         return( -1 );
01918 
01919 #if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
01920     if( need_ca_bit &&
01921         mbedtls_x509_crt_check_key_usage( parent, MBEDTLS_X509_KU_KEY_CERT_SIGN ) != 0 )
01922     {
01923         return( -1 );
01924     }
01925 #endif
01926 
01927     return( 0 );
01928 }
01929 
01930 /*
01931  * Find a suitable parent for child in candidates, or return NULL.
01932  *
01933  * Here suitable is defined as:
01934  *  1. subject name matches child's issuer
01935  *  2. if necessary, the CA bit is set and key usage allows signing certs
01936  *  3. for trusted roots, the signature is correct
01937  *  4. pathlen constraints are satisfied
01938  *
01939  * If there's a suitable candidate which is also time-valid, return the first
01940  * such. Otherwise, return the first suitable candidate (or NULL if there is
01941  * none).
01942  *
01943  * The rationale for this rule is that someone could have a list of trusted
01944  * roots with two versions on the same root with different validity periods.
01945  * (At least one user reported having such a list and wanted it to just work.)
01946  * The reason we don't just require time-validity is that generally there is
01947  * only one version, and if it's expired we want the flags to state that
01948  * rather than NOT_TRUSTED, as would be the case if we required it here.
01949  *
01950  * The rationale for rule 3 (signature for trusted roots) is that users might
01951  * have two versions of the same CA with different keys in their list, and the
01952  * way we select the correct one is by checking the signature (as we don't
01953  * rely on key identifier extensions). (This is one way users might choose to
01954  * handle key rollover, another relies on self-issued certs, see [SIRO].)
01955  *
01956  * Arguments:
01957  *  - [in] child: certificate for which we're looking for a parent
01958  *  - [in] candidates: chained list of potential parents
01959  *  - [in] top: 1 if candidates consists of trusted roots, ie we're at the top
01960  *         of the chain, 0 otherwise
01961  *  - [in] path_cnt: number of intermediates seen so far
01962  *  - [in] self_cnt: number of self-signed intermediates seen so far
01963  *         (will never be greater than path_cnt)
01964  *
01965  * Return value:
01966  *  - the first suitable parent found (see above regarding time-validity)
01967  *  - NULL if no suitable parent was found
01968  */
01969 static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child,
01970                                                   mbedtls_x509_crt *candidates,
01971                                                   int top,
01972                                                   size_t path_cnt,
01973                                                   size_t self_cnt )
01974 {
01975     mbedtls_x509_crt *parent, *badtime_parent = NULL;
01976 
01977     for( parent = candidates; parent != NULL; parent = parent->next )
01978     {
01979         /* basic parenting skills (name, CA bit, key usage) */
01980         if( x509_crt_check_parent( child, parent, top ) != 0 )
01981             continue;
01982 
01983         /* +1 because stored max_pathlen is 1 higher that the actual value */
01984         if( parent->max_pathlen > 0 &&
01985             (size_t) parent->max_pathlen < 1 + path_cnt - self_cnt )
01986         {
01987             continue;
01988         }
01989 
01990         /* Signature */
01991         if( top && x509_crt_check_signature( child, parent ) != 0 )
01992         {
01993             continue;
01994         }
01995 
01996         /* optional time check */
01997         if( mbedtls_x509_time_is_past( &parent->valid_to ) ||
01998             mbedtls_x509_time_is_future( &parent->valid_from ) )
01999         {
02000             if( badtime_parent == NULL )
02001                 badtime_parent = parent;
02002 
02003             continue;
02004         }
02005 
02006         break;
02007     }
02008 
02009     if( parent == NULL )
02010         parent = badtime_parent;
02011 
02012     return( parent );
02013 }
02014 
02015 /*
02016  * Find a parent in trusted CAs or the provided chain, or return NULL.
02017  *
02018  * Searches in trusted CAs first, and return the first suitable parent found
02019  * (see find_parent_in() for definition of suitable).
02020  *
02021  * Arguments:
02022  *  - [in] child: certificate for which we're looking for a parent, followed
02023  *         by a chain of possible intermediates
02024  *  - [in] trust_ca: locally trusted CAs
02025  *  - [out] 1 if parent was found in trust_ca, 0 if found in provided chain
02026  *  - [in] path_cnt: number of intermediates seen so far
02027  *  - [in] self_cnt: number of self-signed intermediates seen so far
02028  *         (will always be no greater than path_cnt)
02029  *
02030  * Return value:
02031  *  - the first suitable parent found (see find_parent_in() for "suitable")
02032  *  - NULL if no suitable parent was found
02033  */
02034 static mbedtls_x509_crt *x509_crt_find_parent( mbedtls_x509_crt *child,
02035                                                mbedtls_x509_crt *trust_ca,
02036                                                int *parent_is_trusted,
02037                                                size_t path_cnt,
02038                                                size_t self_cnt )
02039 {
02040     mbedtls_x509_crt *parent;
02041 
02042     /* Look for a parent in trusted CAs */
02043     *parent_is_trusted = 1;
02044     parent = x509_crt_find_parent_in( child, trust_ca, 1, path_cnt, self_cnt );
02045 
02046     if( parent != NULL )
02047         return( parent );
02048 
02049     /* Look for a parent upwards the chain */
02050     *parent_is_trusted = 0;
02051     return( x509_crt_find_parent_in( child, child->next, 0, path_cnt, self_cnt ) );
02052 }
02053 
02054 /*
02055  * Check if an end-entity certificate is locally trusted
02056  *
02057  * Currently we require such certificates to be self-signed (actually only
02058  * check for self-issued as self-signatures are not checked)
02059  */
02060 static int x509_crt_check_ee_locally_trusted(
02061                     mbedtls_x509_crt *crt,
02062                     mbedtls_x509_crt *trust_ca )
02063 {
02064     mbedtls_x509_crt *cur;
02065 
02066     /* must be self-issued */
02067     if( x509_name_cmp( &crt->issuer, &crt->subject ) != 0 )
02068         return( -1 );
02069 
02070     /* look for an exact match with trusted cert */
02071     for( cur = trust_ca; cur != NULL; cur = cur->next )
02072     {
02073         if( crt->raw.len == cur->raw.len &&
02074             memcmp( crt->raw.p, cur->raw.p, crt->raw.len ) == 0 )
02075         {
02076             return( 0 );
02077         }
02078     }
02079 
02080     /* too bad */
02081     return( -1 );
02082 }
02083 
02084 /*
02085  * Build and verify a certificate chain
02086  *
02087  * Given a peer-provided list of certificates EE, C1, ..., Cn and
02088  * a list of trusted certs R1, ... Rp, try to build and verify a chain
02089  *      EE, Ci1, ... Ciq [, Rj]
02090  * such that every cert in the chain is a child of the next one,
02091  * jumping to a trusted root as early as possible.
02092  *
02093  * Verify that chain and return it with flags for all issues found.
02094  *
02095  * Special cases:
02096  * - EE == Rj -> return a one-element list containing it
02097  * - EE, Ci1, ..., Ciq cannot be continued with a trusted root
02098  *   -> return that chain with NOT_TRUSTED set on Ciq
02099  *
02100  * Arguments:
02101  *  - [in] crt: the cert list EE, C1, ..., Cn
02102  *  - [in] trust_ca: the trusted list R1, ..., Rp
02103  *  - [in] ca_crl, profile: as in verify_with_profile()
02104  *  - [out] ver_chain, chain_len: the built and verified chain
02105  *
02106  * Return value:
02107  *  - non-zero if the chain could not be fully built and examined
02108  *  - 0 is the chain was successfully built and examined,
02109  *      even if it was found to be invalid
02110  */
02111 static int x509_crt_verify_chain(
02112                 mbedtls_x509_crt *crt,
02113                 mbedtls_x509_crt *trust_ca,
02114                 mbedtls_x509_crl *ca_crl,
02115                 const mbedtls_x509_crt_profile *profile,
02116                 x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE],
02117                 size_t *chain_len )
02118 {
02119     uint32_t *flags;
02120     mbedtls_x509_crt *child;
02121     mbedtls_x509_crt *parent;
02122     int parent_is_trusted = 0;
02123     int child_is_trusted = 0;
02124     size_t self_cnt = 0;
02125 
02126     child = crt;
02127     *chain_len = 0;
02128 
02129     while( 1 ) {
02130         /* Add certificate to the verification chain */
02131         ver_chain[*chain_len].crt = child;
02132         flags = &ver_chain[*chain_len].flags;
02133         ++*chain_len;
02134 
02135         /* Check time-validity (all certificates) */
02136         if( mbedtls_x509_time_is_past( &child->valid_to ) )
02137             *flags |= MBEDTLS_X509_BADCERT_EXPIRED;
02138 
02139         if( mbedtls_x509_time_is_future( &child->valid_from ) )
02140             *flags |= MBEDTLS_X509_BADCERT_FUTURE;
02141 
02142         /* Stop here for trusted roots (but not for trusted EE certs) */
02143         if( child_is_trusted )
02144             return( 0 );
02145 
02146         /* Check signature algorithm: MD & PK algs */
02147         if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 )
02148             *flags |= MBEDTLS_X509_BADCERT_BAD_MD;
02149 
02150         if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 )
02151             *flags |= MBEDTLS_X509_BADCERT_BAD_PK;
02152 
02153         /* Special case: EE certs that are locally trusted */
02154         if( *chain_len == 1 &&
02155             x509_crt_check_ee_locally_trusted( child, trust_ca ) == 0 )
02156         {
02157             return( 0 );
02158         }
02159 
02160         /* Look for a parent in trusted CAs or up the chain */
02161         parent = x509_crt_find_parent( child, trust_ca, &parent_is_trusted,
02162                                        *chain_len - 1, self_cnt );
02163 
02164         /* No parent? We're done here */
02165         if( parent == NULL )
02166         {
02167             *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
02168             return( 0 );
02169         }
02170 
02171         /* Count intermediate self-issued (not necessarily self-signed) certs.
02172          * These can occur with some strategies for key rollover, see [SIRO],
02173          * and should be excluded from max_pathlen checks. */
02174         if( *chain_len != 1 &&
02175             x509_name_cmp( &child->issuer, &child->subject ) == 0 )
02176         {
02177             self_cnt++;
02178         }
02179 
02180         /* path_cnt is 0 for the first intermediate CA,
02181          * and if parent is trusted it's not an intermediate CA */
02182         if( ! parent_is_trusted &&
02183             *chain_len > MBEDTLS_X509_MAX_INTERMEDIATE_CA )
02184         {
02185             /* return immediately to avoid overflow the chain array */
02186             return( MBEDTLS_ERR_X509_FATAL_ERROR );
02187         }
02188 
02189         /* if parent is trusted, the signature was checked by find_parent() */
02190         if( ! parent_is_trusted && x509_crt_check_signature( child, parent ) != 0 )
02191             *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
02192 
02193         /* check size of signing key */
02194         if( x509_profile_check_key( profile, &parent->pk ) != 0 )
02195             *flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
02196 
02197 #if defined(MBEDTLS_X509_CRL_PARSE_C)
02198         /* Check trusted CA's CRL for the given crt */
02199         *flags |= x509_crt_verifycrl( child, parent, ca_crl, profile );
02200 #else
02201         (void) ca_crl;
02202 #endif
02203 
02204         /* prepare for next iteration */
02205         child = parent;
02206         parent = NULL;
02207         child_is_trusted = parent_is_trusted;
02208     }
02209 }
02210 
02211 /*
02212  * Check for CN match
02213  */
02214 static int x509_crt_check_cn( const mbedtls_x509_buf *name,
02215                               const char *cn, size_t cn_len )
02216 {
02217     /* try exact match */
02218     if( name->len == cn_len &&
02219         x509_memcasecmp( cn, name->p, cn_len ) == 0 )
02220     {
02221         return( 0 );
02222     }
02223 
02224     /* try wildcard match */
02225     if( x509_check_wildcard( cn, name ) == 0 )
02226     {
02227         return( 0 );
02228     }
02229 
02230     return( -1 );
02231 }
02232 
02233 /*
02234  * Verify the requested CN - only call this if cn is not NULL!
02235  */
02236 static void x509_crt_verify_name( const mbedtls_x509_crt *crt,
02237                                   const char *cn,
02238                                   uint32_t *flags )
02239 {
02240     const mbedtls_x509_name *name;
02241     const mbedtls_x509_sequence *cur;
02242     size_t cn_len = strlen( cn );
02243 
02244     if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
02245     {
02246         for( cur = &crt->subject_alt_names; cur != NULL; cur = cur->next )
02247         {
02248             if( x509_crt_check_cn( &cur->buf, cn, cn_len ) == 0 )
02249                 break;
02250         }
02251 
02252         if( cur == NULL )
02253             *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
02254     }
02255     else
02256     {
02257         for( name = &crt->subject; name != NULL; name = name->next )
02258         {
02259             if( MBEDTLS_OID_CMP( MBEDTLS_OID_AT_CN, &name->oid ) == 0 &&
02260                 x509_crt_check_cn( &name->val, cn, cn_len ) == 0 )
02261             {
02262                 break;
02263             }
02264         }
02265 
02266         if( name == NULL )
02267             *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
02268     }
02269 }
02270 
02271 /*
02272  * Merge the flags for all certs in the chain, after calling callback
02273  */
02274 static int x509_crt_merge_flags_with_cb(
02275            uint32_t *flags,
02276            x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE],
02277            size_t chain_len,
02278            int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
02279            void *p_vrfy )
02280 {
02281     int ret;
02282     size_t i;
02283     uint32_t cur_flags;
02284 
02285     for( i = chain_len; i != 0; --i )
02286     {
02287         cur_flags = ver_chain[i-1].flags;
02288 
02289         if( NULL != f_vrfy )
02290             if( ( ret = f_vrfy( p_vrfy, ver_chain[i-1].crt, (int) i-1, &cur_flags ) ) != 0 )
02291                 return( ret );
02292 
02293         *flags |= cur_flags;
02294     }
02295 
02296     return( 0 );
02297 }
02298 
02299 /*
02300  * Verify the certificate validity
02301  */
02302 int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt,
02303                      mbedtls_x509_crt *trust_ca,
02304                      mbedtls_x509_crl *ca_crl,
02305                      const char *cn, uint32_t *flags,
02306                      int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
02307                      void *p_vrfy )
02308 {
02309     return( mbedtls_x509_crt_verify_with_profile( crt, trust_ca, ca_crl,
02310                 &mbedtls_x509_crt_profile_default, cn, flags, f_vrfy, p_vrfy ) );
02311 }
02312 
02313 /*
02314  * Verify the certificate validity, with profile
02315  *
02316  * This function:
02317  *  - checks the requested CN (if any)
02318  *  - checks the type and size of the EE cert's key,
02319  *    as that isn't done as part of chain building/verification currently
02320  *  - builds and verifies the chain
02321  *  - then calls the callback and merges the flags
02322  */
02323 int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
02324                      mbedtls_x509_crt *trust_ca,
02325                      mbedtls_x509_crl *ca_crl,
02326                      const mbedtls_x509_crt_profile *profile,
02327                      const char *cn, uint32_t *flags,
02328                      int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
02329                      void *p_vrfy )
02330 {
02331     int ret;
02332     mbedtls_pk_type_t pk_type;
02333     x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE];
02334     size_t chain_len;
02335     uint32_t *ee_flags = &ver_chain[0].flags;
02336 
02337     *flags = 0;
02338     memset( ver_chain, 0, sizeof( ver_chain ) );
02339     chain_len = 0;
02340 
02341     if( profile == NULL )
02342     {
02343         ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA;
02344         goto exit;
02345     }
02346 
02347     /* check name if requested */
02348     if( cn != NULL )
02349         x509_crt_verify_name( crt, cn, ee_flags );
02350 
02351     /* Check the type and size of the key */
02352     pk_type = mbedtls_pk_get_type( &crt->pk );
02353 
02354     if( x509_profile_check_pk_alg( profile, pk_type ) != 0 )
02355         *ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK;
02356 
02357     if( x509_profile_check_key( profile, &crt->pk ) != 0 )
02358         *ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
02359 
02360     /* Check the chain */
02361     ret = x509_crt_verify_chain( crt, trust_ca, ca_crl, profile,
02362                                  ver_chain, &chain_len );
02363     if( ret != 0 )
02364         goto exit;
02365 
02366     /* Build final flags, calling callback on the way if any */
02367     ret = x509_crt_merge_flags_with_cb( flags,
02368                                         ver_chain, chain_len, f_vrfy, p_vrfy );
02369 
02370 exit:
02371     /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by
02372      * the SSL module for authmode optional, but non-zero return from the
02373      * callback means a fatal error so it shouldn't be ignored */
02374     if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED )
02375         ret = MBEDTLS_ERR_X509_FATAL_ERROR;
02376 
02377     if( ret != 0 )
02378     {
02379         *flags = (uint32_t) -1;
02380         return( ret );
02381     }
02382 
02383     if( *flags != 0 )
02384         return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED );
02385 
02386     return( 0 );
02387 }
02388 
02389 /*
02390  * Initialize a certificate chain
02391  */
02392 void mbedtls_x509_crt_init( mbedtls_x509_crt *crt )
02393 {
02394     memset( crt, 0, sizeof(mbedtls_x509_crt) );
02395 }
02396 
02397 /*
02398  * Unallocate all certificate data
02399  */
02400 void mbedtls_x509_crt_free( mbedtls_x509_crt *crt )
02401 {
02402     mbedtls_x509_crt *cert_cur = crt;
02403     mbedtls_x509_crt *cert_prv;
02404     mbedtls_x509_name *name_cur;
02405     mbedtls_x509_name *name_prv;
02406     mbedtls_x509_sequence *seq_cur;
02407     mbedtls_x509_sequence *seq_prv;
02408 
02409     if( crt == NULL )
02410         return;
02411 
02412     do
02413     {
02414         mbedtls_pk_free( &cert_cur->pk );
02415 
02416 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
02417         mbedtls_free( cert_cur->sig_opts );
02418 #endif
02419 
02420         name_cur = cert_cur->issuer.next;
02421         while( name_cur != NULL )
02422         {
02423             name_prv = name_cur;
02424             name_cur = name_cur->next;
02425             mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) );
02426             mbedtls_free( name_prv );
02427         }
02428 
02429         name_cur = cert_cur->subject.next;
02430         while( name_cur != NULL )
02431         {
02432             name_prv = name_cur;
02433             name_cur = name_cur->next;
02434             mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) );
02435             mbedtls_free( name_prv );
02436         }
02437 
02438         seq_cur = cert_cur->ext_key_usage.next;
02439         while( seq_cur != NULL )
02440         {
02441             seq_prv = seq_cur;
02442             seq_cur = seq_cur->next;
02443             mbedtls_platform_zeroize( seq_prv,
02444                                       sizeof( mbedtls_x509_sequence ) );
02445             mbedtls_free( seq_prv );
02446         }
02447 
02448         seq_cur = cert_cur->subject_alt_names.next;
02449         while( seq_cur != NULL )
02450         {
02451             seq_prv = seq_cur;
02452             seq_cur = seq_cur->next;
02453             mbedtls_platform_zeroize( seq_prv,
02454                                       sizeof( mbedtls_x509_sequence ) );
02455             mbedtls_free( seq_prv );
02456         }
02457 
02458         if( cert_cur->raw.p != NULL )
02459         {
02460             mbedtls_platform_zeroize( cert_cur->raw.p, cert_cur->raw.len );
02461             mbedtls_free( cert_cur->raw.p );
02462         }
02463 
02464         cert_cur = cert_cur->next;
02465     }
02466     while( cert_cur != NULL );
02467 
02468     cert_cur = crt;
02469     do
02470     {
02471         cert_prv = cert_cur;
02472         cert_cur = cert_cur->next;
02473 
02474         mbedtls_platform_zeroize( cert_prv, sizeof( mbedtls_x509_crt ) );
02475         if( cert_prv != crt )
02476             mbedtls_free( cert_prv );
02477     }
02478     while( cert_cur != NULL );
02479 }
02480 
02481 #endif /* MBEDTLS_X509_CRT_PARSE_C */