Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers x509.c Source File

x509.c

00001 /*
00002  *  X.509 common functions for 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 
00032 #if !defined(MBEDTLS_CONFIG_FILE)
00033 #include "mbedtls/config.h"
00034 #else
00035 #include MBEDTLS_CONFIG_FILE
00036 #endif
00037 
00038 #if defined(MBEDTLS_X509_USE_C)
00039 
00040 #include "mbedtls/x509.h"
00041 #include "mbedtls/asn1.h"
00042 #include "mbedtls/oid.h"
00043 
00044 #include <stdio.h>
00045 #include <string.h>
00046 
00047 #if defined(MBEDTLS_PEM_PARSE_C)
00048 #include "mbedtls/pem.h"
00049 #endif
00050 
00051 #if defined(MBEDTLS_PLATFORM_C)
00052 #include "mbedtls/platform.h"
00053 #else
00054 #include <stdio.h>
00055 #include <stdlib.h>
00056 #define mbedtls_free      free
00057 #define mbedtls_calloc    calloc
00058 #define mbedtls_printf    printf
00059 #define mbedtls_snprintf  snprintf
00060 #endif
00061 
00062 #if defined(MBEDTLS_HAVE_TIME)
00063 #include "mbedtls/platform_time.h"
00064 #endif
00065 #if defined(MBEDTLS_HAVE_TIME_DATE)
00066 #include "mbedtls/platform_util.h"
00067 #include <time.h>
00068 #endif
00069 
00070 #define CHECK(code) if( ( ret = ( code ) ) != 0 ){ return( ret ); }
00071 #define CHECK_RANGE(min, max, val)                      \
00072     do                                                  \
00073     {                                                   \
00074         if( ( val ) < ( min ) || ( val ) > ( max ) )    \
00075         {                                               \
00076             return( ret );                              \
00077         }                                               \
00078     } while( 0 )
00079 
00080 /*
00081  *  CertificateSerialNumber  ::=  INTEGER
00082  */
00083 int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end,
00084                      mbedtls_x509_buf *serial )
00085 {
00086     int ret;
00087 
00088     if( ( end - *p ) < 1 )
00089         return( MBEDTLS_ERR_X509_INVALID_SERIAL +
00090                 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
00091 
00092     if( **p != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2 ) &&
00093         **p !=   MBEDTLS_ASN1_INTEGER )
00094         return( MBEDTLS_ERR_X509_INVALID_SERIAL +
00095                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
00096 
00097     serial->tag = *(*p)++;
00098 
00099     if( ( ret = mbedtls_asn1_get_len( p, end, &serial->len ) ) != 0 )
00100         return( MBEDTLS_ERR_X509_INVALID_SERIAL + ret );
00101 
00102     serial->p = *p;
00103     *p += serial->len;
00104 
00105     return( 0 );
00106 }
00107 
00108 /* Get an algorithm identifier without parameters (eg for signatures)
00109  *
00110  *  AlgorithmIdentifier  ::=  SEQUENCE  {
00111  *       algorithm               OBJECT IDENTIFIER,
00112  *       parameters              ANY DEFINED BY algorithm OPTIONAL  }
00113  */
00114 int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end,
00115                        mbedtls_x509_buf *alg )
00116 {
00117     int ret;
00118 
00119     if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 )
00120         return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
00121 
00122     return( 0 );
00123 }
00124 
00125 /*
00126  * Parse an algorithm identifier with (optional) parameters
00127  */
00128 int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end,
00129                   mbedtls_x509_buf *alg, mbedtls_x509_buf *params )
00130 {
00131     int ret;
00132 
00133     if( ( ret = mbedtls_asn1_get_alg( p, end, alg, params ) ) != 0 )
00134         return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
00135 
00136     return( 0 );
00137 }
00138 
00139 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
00140 /*
00141  * HashAlgorithm ::= AlgorithmIdentifier
00142  *
00143  * AlgorithmIdentifier  ::=  SEQUENCE  {
00144  *      algorithm               OBJECT IDENTIFIER,
00145  *      parameters              ANY DEFINED BY algorithm OPTIONAL  }
00146  *
00147  * For HashAlgorithm, parameters MUST be NULL or absent.
00148  */
00149 static int x509_get_hash_alg( const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg )
00150 {
00151     int ret;
00152     unsigned char *p;
00153     const unsigned char *end;
00154     mbedtls_x509_buf md_oid;
00155     size_t len;
00156 
00157     /* Make sure we got a SEQUENCE and setup bounds */
00158     if( alg->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
00159         return( MBEDTLS_ERR_X509_INVALID_ALG +
00160                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
00161 
00162     p = (unsigned char *) alg->p;
00163     end = p + alg->len;
00164 
00165     if( p >= end )
00166         return( MBEDTLS_ERR_X509_INVALID_ALG +
00167                 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
00168 
00169     /* Parse md_oid */
00170     md_oid.tag = *p;
00171 
00172     if( ( ret = mbedtls_asn1_get_tag( &p, end, &md_oid.len, MBEDTLS_ASN1_OID ) ) != 0 )
00173         return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
00174 
00175     md_oid.p = p;
00176     p += md_oid.len;
00177 
00178     /* Get md_alg from md_oid */
00179     if( ( ret = mbedtls_oid_get_md_alg( &md_oid, md_alg ) ) != 0 )
00180         return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
00181 
00182     /* Make sure params is absent of NULL */
00183     if( p == end )
00184         return( 0 );
00185 
00186     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_NULL ) ) != 0 || len != 0 )
00187         return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
00188 
00189     if( p != end )
00190         return( MBEDTLS_ERR_X509_INVALID_ALG +
00191                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
00192 
00193     return( 0 );
00194 }
00195 
00196 /*
00197  *    RSASSA-PSS-params  ::=  SEQUENCE  {
00198  *       hashAlgorithm     [0] HashAlgorithm DEFAULT sha1Identifier,
00199  *       maskGenAlgorithm  [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier,
00200  *       saltLength        [2] INTEGER DEFAULT 20,
00201  *       trailerField      [3] INTEGER DEFAULT 1  }
00202  *    -- Note that the tags in this Sequence are explicit.
00203  *
00204  * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value
00205  * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other
00206  * option. Enfore this at parsing time.
00207  */
00208 int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params,
00209                                 mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md,
00210                                 int *salt_len )
00211 {
00212     int ret;
00213     unsigned char *p;
00214     const unsigned char *end, *end2;
00215     size_t len;
00216     mbedtls_x509_buf alg_id, alg_params;
00217 
00218     /* First set everything to defaults */
00219     *md_alg = MBEDTLS_MD_SHA1;
00220     *mgf_md = MBEDTLS_MD_SHA1;
00221     *salt_len = 20;
00222 
00223     /* Make sure params is a SEQUENCE and setup bounds */
00224     if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
00225         return( MBEDTLS_ERR_X509_INVALID_ALG +
00226                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
00227 
00228     p = (unsigned char *) params->p;
00229     end = p + params->len;
00230 
00231     if( p == end )
00232         return( 0 );
00233 
00234     /*
00235      * HashAlgorithm
00236      */
00237     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
00238                     MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 )
00239     {
00240         end2 = p + len;
00241 
00242         /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */
00243         if( ( ret = mbedtls_x509_get_alg_null( &p, end2, &alg_id ) ) != 0 )
00244             return( ret );
00245 
00246         if( ( ret = mbedtls_oid_get_md_alg( &alg_id, md_alg ) ) != 0 )
00247             return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
00248 
00249         if( p != end2 )
00250             return( MBEDTLS_ERR_X509_INVALID_ALG +
00251                     MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
00252     }
00253     else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
00254         return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
00255 
00256     if( p == end )
00257         return( 0 );
00258 
00259     /*
00260      * MaskGenAlgorithm
00261      */
00262     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
00263                     MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 )
00264     {
00265         end2 = p + len;
00266 
00267         /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */
00268         if( ( ret = mbedtls_x509_get_alg( &p, end2, &alg_id, &alg_params ) ) != 0 )
00269             return( ret );
00270 
00271         /* Only MFG1 is recognised for now */
00272         if( MBEDTLS_OID_CMP( MBEDTLS_OID_MGF1, &alg_id ) != 0 )
00273             return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE +
00274                     MBEDTLS_ERR_OID_NOT_FOUND );
00275 
00276         /* Parse HashAlgorithm */
00277         if( ( ret = x509_get_hash_alg( &alg_params, mgf_md ) ) != 0 )
00278             return( ret );
00279 
00280         if( p != end2 )
00281             return( MBEDTLS_ERR_X509_INVALID_ALG +
00282                     MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
00283     }
00284     else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
00285         return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
00286 
00287     if( p == end )
00288         return( 0 );
00289 
00290     /*
00291      * salt_len
00292      */
00293     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
00294                     MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 2 ) ) == 0 )
00295     {
00296         end2 = p + len;
00297 
00298         if( ( ret = mbedtls_asn1_get_int( &p, end2, salt_len ) ) != 0 )
00299             return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
00300 
00301         if( p != end2 )
00302             return( MBEDTLS_ERR_X509_INVALID_ALG +
00303                     MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
00304     }
00305     else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
00306         return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
00307 
00308     if( p == end )
00309         return( 0 );
00310 
00311     /*
00312      * trailer_field (if present, must be 1)
00313      */
00314     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
00315                     MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 3 ) ) == 0 )
00316     {
00317         int trailer_field;
00318 
00319         end2 = p + len;
00320 
00321         if( ( ret = mbedtls_asn1_get_int( &p, end2, &trailer_field ) ) != 0 )
00322             return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
00323 
00324         if( p != end2 )
00325             return( MBEDTLS_ERR_X509_INVALID_ALG +
00326                     MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
00327 
00328         if( trailer_field != 1 )
00329             return( MBEDTLS_ERR_X509_INVALID_ALG );
00330     }
00331     else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
00332         return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
00333 
00334     if( p != end )
00335         return( MBEDTLS_ERR_X509_INVALID_ALG +
00336                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
00337 
00338     return( 0 );
00339 }
00340 #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
00341 
00342 /*
00343  *  AttributeTypeAndValue ::= SEQUENCE {
00344  *    type     AttributeType,
00345  *    value    AttributeValue }
00346  *
00347  *  AttributeType ::= OBJECT IDENTIFIER
00348  *
00349  *  AttributeValue ::= ANY DEFINED BY AttributeType
00350  */
00351 static int x509_get_attr_type_value( unsigned char **p,
00352                                      const unsigned char *end,
00353                                      mbedtls_x509_name *cur )
00354 {
00355     int ret;
00356     size_t len;
00357     mbedtls_x509_buf *oid;
00358     mbedtls_x509_buf *val;
00359 
00360     if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
00361             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
00362         return( MBEDTLS_ERR_X509_INVALID_NAME + ret );
00363 
00364     end = *p + len;
00365 
00366     if( ( end - *p ) < 1 )
00367         return( MBEDTLS_ERR_X509_INVALID_NAME +
00368                 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
00369 
00370     oid = &cur->oid;
00371     oid->tag = **p;
00372 
00373     if( ( ret = mbedtls_asn1_get_tag( p, end, &oid->len, MBEDTLS_ASN1_OID ) ) != 0 )
00374         return( MBEDTLS_ERR_X509_INVALID_NAME + ret );
00375 
00376     oid->p = *p;
00377     *p += oid->len;
00378 
00379     if( ( end - *p ) < 1 )
00380         return( MBEDTLS_ERR_X509_INVALID_NAME +
00381                 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
00382 
00383     if( **p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING      &&
00384         **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING &&
00385         **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING &&
00386         **p != MBEDTLS_ASN1_BIT_STRING )
00387         return( MBEDTLS_ERR_X509_INVALID_NAME +
00388                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
00389 
00390     val = &cur->val;
00391     val->tag = *(*p)++;
00392 
00393     if( ( ret = mbedtls_asn1_get_len( p, end, &val->len ) ) != 0 )
00394         return( MBEDTLS_ERR_X509_INVALID_NAME + ret );
00395 
00396     val->p = *p;
00397     *p += val->len;
00398 
00399     if( *p != end )
00400     {
00401         return( MBEDTLS_ERR_X509_INVALID_NAME +
00402                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
00403     }
00404 
00405     cur->next = NULL;
00406 
00407     return( 0 );
00408 }
00409 
00410 /*
00411  *  Name ::= CHOICE { -- only one possibility for now --
00412  *       rdnSequence  RDNSequence }
00413  *
00414  *  RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
00415  *
00416  *  RelativeDistinguishedName ::=
00417  *    SET OF AttributeTypeAndValue
00418  *
00419  *  AttributeTypeAndValue ::= SEQUENCE {
00420  *    type     AttributeType,
00421  *    value    AttributeValue }
00422  *
00423  *  AttributeType ::= OBJECT IDENTIFIER
00424  *
00425  *  AttributeValue ::= ANY DEFINED BY AttributeType
00426  *
00427  * The data structure is optimized for the common case where each RDN has only
00428  * one element, which is represented as a list of AttributeTypeAndValue.
00429  * For the general case we still use a flat list, but we mark elements of the
00430  * same set so that they are "merged" together in the functions that consume
00431  * this list, eg mbedtls_x509_dn_gets().
00432  */
00433 int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end,
00434                    mbedtls_x509_name *cur )
00435 {
00436     int ret;
00437     size_t set_len;
00438     const unsigned char *end_set;
00439 
00440     /* don't use recursion, we'd risk stack overflow if not optimized */
00441     while( 1 )
00442     {
00443         /*
00444          * parse SET
00445          */
00446         if( ( ret = mbedtls_asn1_get_tag( p, end, &set_len,
00447                 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ) != 0 )
00448             return( MBEDTLS_ERR_X509_INVALID_NAME + ret );
00449 
00450         end_set  = *p + set_len;
00451 
00452         while( 1 )
00453         {
00454             if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 )
00455                 return( ret );
00456 
00457             if( *p == end_set )
00458                 break;
00459 
00460             /* Mark this item as being no the only one in a set */
00461             cur->next_merged = 1;
00462 
00463             cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) );
00464 
00465             if( cur->next == NULL )
00466                 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
00467 
00468             cur = cur->next;
00469         }
00470 
00471         /*
00472          * continue until end of SEQUENCE is reached
00473          */
00474         if( *p == end )
00475             return( 0 );
00476 
00477         cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) );
00478 
00479         if( cur->next == NULL )
00480             return( MBEDTLS_ERR_X509_ALLOC_FAILED );
00481 
00482         cur = cur->next;
00483     }
00484 }
00485 
00486 static int x509_parse_int( unsigned char **p, size_t n, int *res )
00487 {
00488     *res = 0;
00489 
00490     for( ; n > 0; --n )
00491     {
00492         if( ( **p < '0') || ( **p > '9' ) )
00493             return ( MBEDTLS_ERR_X509_INVALID_DATE );
00494 
00495         *res *= 10;
00496         *res += ( *(*p)++ - '0' );
00497     }
00498 
00499     return( 0 );
00500 }
00501 
00502 static int x509_date_is_valid(const mbedtls_x509_time *t )
00503 {
00504     int ret = MBEDTLS_ERR_X509_INVALID_DATE;
00505     int month_len;
00506 
00507     CHECK_RANGE( 0, 9999, t->year );
00508     CHECK_RANGE( 0, 23,   t->hour );
00509     CHECK_RANGE( 0, 59,   t->min  );
00510     CHECK_RANGE( 0, 59,   t->sec  );
00511 
00512     switch( t->mon )
00513     {
00514         case 1: case 3: case 5: case 7: case 8: case 10: case 12:
00515             month_len = 31;
00516             break;
00517         case 4: case 6: case 9: case 11:
00518             month_len = 30;
00519             break;
00520         case 2:
00521             if( ( !( t->year % 4 ) && t->year % 100 ) ||
00522                 !( t->year % 400 ) )
00523                 month_len = 29;
00524             else
00525                 month_len = 28;
00526             break;
00527         default:
00528             return( ret );
00529     }
00530     CHECK_RANGE( 1, month_len, t->day );
00531 
00532     return( 0 );
00533 }
00534 
00535 /*
00536  * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4)
00537  * field.
00538  */
00539 static int x509_parse_time( unsigned char **p, size_t len, size_t yearlen,
00540                             mbedtls_x509_time *tm )
00541 {
00542     int ret;
00543 
00544     /*
00545      * Minimum length is 10 or 12 depending on yearlen
00546      */
00547     if ( len < yearlen + 8 )
00548         return ( MBEDTLS_ERR_X509_INVALID_DATE );
00549     len -= yearlen + 8;
00550 
00551     /*
00552      * Parse year, month, day, hour, minute
00553      */
00554     CHECK( x509_parse_int( p, yearlen, &tm->year ) );
00555     if ( 2 == yearlen )
00556     {
00557         if ( tm->year < 50 )
00558             tm->year += 100;
00559 
00560         tm->year += 1900;
00561     }
00562 
00563     CHECK( x509_parse_int( p, 2, &tm->mon ) );
00564     CHECK( x509_parse_int( p, 2, &tm->day ) );
00565     CHECK( x509_parse_int( p, 2, &tm->hour ) );
00566     CHECK( x509_parse_int( p, 2, &tm->min ) );
00567 
00568     /*
00569      * Parse seconds if present
00570      */
00571     if ( len >= 2 )
00572     {
00573         CHECK( x509_parse_int( p, 2, &tm->sec ) );
00574         len -= 2;
00575     }
00576     else
00577         return ( MBEDTLS_ERR_X509_INVALID_DATE );
00578 
00579     /*
00580      * Parse trailing 'Z' if present
00581      */
00582     if ( 1 == len && 'Z' == **p )
00583     {
00584         (*p)++;
00585         len--;
00586     }
00587 
00588     /*
00589      * We should have parsed all characters at this point
00590      */
00591     if ( 0 != len )
00592         return ( MBEDTLS_ERR_X509_INVALID_DATE );
00593 
00594     CHECK( x509_date_is_valid( tm ) );
00595 
00596     return ( 0 );
00597 }
00598 
00599 /*
00600  *  Time ::= CHOICE {
00601  *       utcTime        UTCTime,
00602  *       generalTime    GeneralizedTime }
00603  */
00604 int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end,
00605                            mbedtls_x509_time *tm )
00606 {
00607     int ret;
00608     size_t len, year_len;
00609     unsigned char tag;
00610 
00611     if( ( end - *p ) < 1 )
00612         return( MBEDTLS_ERR_X509_INVALID_DATE +
00613                 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
00614 
00615     tag = **p;
00616 
00617     if( tag == MBEDTLS_ASN1_UTC_TIME )
00618         year_len = 2;
00619     else if( tag == MBEDTLS_ASN1_GENERALIZED_TIME )
00620         year_len = 4;
00621     else
00622         return( MBEDTLS_ERR_X509_INVALID_DATE +
00623                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
00624 
00625     (*p)++;
00626     ret = mbedtls_asn1_get_len( p, end, &len );
00627 
00628     if( ret != 0 )
00629         return( MBEDTLS_ERR_X509_INVALID_DATE + ret );
00630 
00631     return x509_parse_time( p, len, year_len, tm );
00632 }
00633 
00634 int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig )
00635 {
00636     int ret;
00637     size_t len;
00638     int tag_type;
00639 
00640     if( ( end - *p ) < 1 )
00641         return( MBEDTLS_ERR_X509_INVALID_SIGNATURE +
00642                 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
00643 
00644     tag_type = **p;
00645 
00646     if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 )
00647         return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + ret );
00648 
00649     sig->tag = tag_type;
00650     sig->len = len;
00651     sig->p = *p;
00652 
00653     *p += len;
00654 
00655     return( 0 );
00656 }
00657 
00658 /*
00659  * Get signature algorithm from alg OID and optional parameters
00660  */
00661 int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params,
00662                       mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg,
00663                       void **sig_opts )
00664 {
00665     int ret;
00666 
00667     if( *sig_opts != NULL )
00668         return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
00669 
00670     if( ( ret = mbedtls_oid_get_sig_alg( sig_oid, md_alg, pk_alg ) ) != 0 )
00671         return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + ret );
00672 
00673 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
00674     if( *pk_alg == MBEDTLS_PK_RSASSA_PSS )
00675     {
00676         mbedtls_pk_rsassa_pss_options *pss_opts;
00677 
00678         pss_opts = mbedtls_calloc( 1, sizeof( mbedtls_pk_rsassa_pss_options ) );
00679         if( pss_opts == NULL )
00680             return( MBEDTLS_ERR_X509_ALLOC_FAILED );
00681 
00682         ret = mbedtls_x509_get_rsassa_pss_params( sig_params,
00683                                           md_alg,
00684                                           &pss_opts->mgf1_hash_id,
00685                                           &pss_opts->expected_salt_len );
00686         if( ret != 0 )
00687         {
00688             mbedtls_free( pss_opts );
00689             return( ret );
00690         }
00691 
00692         *sig_opts = (void *) pss_opts;
00693     }
00694     else
00695 #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
00696     {
00697         /* Make sure parameters are absent or NULL */
00698         if( ( sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0 ) ||
00699               sig_params->len != 0 )
00700         return( MBEDTLS_ERR_X509_INVALID_ALG );
00701     }
00702 
00703     return( 0 );
00704 }
00705 
00706 /*
00707  * X.509 Extensions (No parsing of extensions, pointer should
00708  * be either manually updated or extensions should be parsed!)
00709  */
00710 int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end,
00711                           mbedtls_x509_buf *ext, int tag )
00712 {
00713     int ret;
00714     size_t len;
00715 
00716     /* Extension structure use EXPLICIT tagging. That is, the actual
00717      * `Extensions` structure is wrapped by a tag-length pair using
00718      * the respective context-specific tag. */
00719     ret = mbedtls_asn1_get_tag( p, end, &ext->len,
00720               MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag );
00721     if( ret != 0 )
00722         return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
00723 
00724     ext->tag = MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag;
00725     ext->p   = *p;
00726     end      = *p + ext->len;
00727 
00728     /*
00729      * Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
00730      */
00731     if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
00732             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
00733         return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
00734 
00735     if( end != *p + len )
00736         return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
00737                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
00738 
00739     return( 0 );
00740 }
00741 
00742 /*
00743  * Store the name in printable form into buf; no more
00744  * than size characters will be written
00745  */
00746 int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn )
00747 {
00748     int ret;
00749     size_t i, n;
00750     unsigned char c, merge = 0;
00751     const mbedtls_x509_name *name;
00752     const char *short_name = NULL;
00753     char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p;
00754 
00755     memset( s, 0, sizeof( s ) );
00756 
00757     name = dn;
00758     p = buf;
00759     n = size;
00760 
00761     while( name != NULL )
00762     {
00763         if( !name->oid.p )
00764         {
00765             name = name->next;
00766             continue;
00767         }
00768 
00769         if( name != dn )
00770         {
00771             ret = mbedtls_snprintf( p, n, merge ? " + " : ", " );
00772             MBEDTLS_X509_SAFE_SNPRINTF;
00773         }
00774 
00775         ret = mbedtls_oid_get_attr_short_name( &name->oid, &short_name );
00776 
00777         if( ret == 0 )
00778             ret = mbedtls_snprintf( p, n, "%s=", short_name );
00779         else
00780             ret = mbedtls_snprintf( p, n, "\?\?=" );
00781         MBEDTLS_X509_SAFE_SNPRINTF;
00782 
00783         for( i = 0; i < name->val.len; i++ )
00784         {
00785             if( i >= sizeof( s ) - 1 )
00786                 break;
00787 
00788             c = name->val.p[i];
00789             if( c < 32 || c == 127 || ( c > 128 && c < 160 ) )
00790                  s[i] = '?';
00791             else s[i] = c;
00792         }
00793         s[i] = '\0';
00794         ret = mbedtls_snprintf( p, n, "%s", s );
00795         MBEDTLS_X509_SAFE_SNPRINTF;
00796 
00797         merge = name->next_merged;
00798         name = name->next;
00799     }
00800 
00801     return( (int) ( size - n ) );
00802 }
00803 
00804 /*
00805  * Store the serial in printable form into buf; no more
00806  * than size characters will be written
00807  */
00808 int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial )
00809 {
00810     int ret;
00811     size_t i, n, nr;
00812     char *p;
00813 
00814     p = buf;
00815     n = size;
00816 
00817     nr = ( serial->len <= 32 )
00818         ? serial->len  : 28;
00819 
00820     for( i = 0; i < nr; i++ )
00821     {
00822         if( i == 0 && nr > 1 && serial->p[i] == 0x0 )
00823             continue;
00824 
00825         ret = mbedtls_snprintf( p, n, "%02X%s",
00826                 serial->p[i], ( i < nr - 1 ) ? ":" : "" );
00827         MBEDTLS_X509_SAFE_SNPRINTF;
00828     }
00829 
00830     if( nr != serial->len )
00831     {
00832         ret = mbedtls_snprintf( p, n, "...." );
00833         MBEDTLS_X509_SAFE_SNPRINTF;
00834     }
00835 
00836     return( (int) ( size - n ) );
00837 }
00838 
00839 /*
00840  * Helper for writing signature algorithms
00841  */
00842 int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid,
00843                        mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg,
00844                        const void *sig_opts )
00845 {
00846     int ret;
00847     char *p = buf;
00848     size_t n = size;
00849     const char *desc = NULL;
00850 
00851     ret = mbedtls_oid_get_sig_alg_desc( sig_oid, &desc );
00852     if( ret != 0 )
00853         ret = mbedtls_snprintf( p, n, "???"  );
00854     else
00855         ret = mbedtls_snprintf( p, n, "%s", desc );
00856     MBEDTLS_X509_SAFE_SNPRINTF;
00857 
00858 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
00859     if( pk_alg == MBEDTLS_PK_RSASSA_PSS )
00860     {
00861         const mbedtls_pk_rsassa_pss_options *pss_opts;
00862         const mbedtls_md_info_t *md_info, *mgf_md_info;
00863 
00864         pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts;
00865 
00866         md_info = mbedtls_md_info_from_type( md_alg );
00867         mgf_md_info = mbedtls_md_info_from_type( pss_opts->mgf1_hash_id );
00868 
00869         ret = mbedtls_snprintf( p, n, " (%s, MGF1-%s, 0x%02X)",
00870                               md_info ? mbedtls_md_get_name( md_info ) : "???",
00871                               mgf_md_info ? mbedtls_md_get_name( mgf_md_info ) : "???",
00872                               pss_opts->expected_salt_len );
00873         MBEDTLS_X509_SAFE_SNPRINTF;
00874     }
00875 #else
00876     ((void) pk_alg);
00877     ((void) md_alg);
00878     ((void) sig_opts);
00879 #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
00880 
00881     return( (int)( size - n ) );
00882 }
00883 
00884 /*
00885  * Helper for writing "RSA key size", "EC key size", etc
00886  */
00887 int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name )
00888 {
00889     char *p = buf;
00890     size_t n = buf_size;
00891     int ret;
00892 
00893     ret = mbedtls_snprintf( p, n, "%s key size", name );
00894     MBEDTLS_X509_SAFE_SNPRINTF;
00895 
00896     return( 0 );
00897 }
00898 
00899 #if defined(MBEDTLS_HAVE_TIME_DATE)
00900 /*
00901  * Set the time structure to the current time.
00902  * Return 0 on success, non-zero on failure.
00903  */
00904 static int x509_get_current_time( mbedtls_x509_time *now )
00905 {
00906     struct tm *lt, tm_buf;
00907     mbedtls_time_t tt;
00908     int ret = 0;
00909 
00910     tt = mbedtls_time( NULL );
00911     lt = mbedtls_platform_gmtime_r( &tt, &tm_buf );
00912 
00913     if( lt == NULL )
00914         ret = -1;
00915     else
00916     {
00917         now->year = lt->tm_year + 1900;
00918         now->mon  = lt->tm_mon  + 1;
00919         now->day  = lt->tm_mday;
00920         now->hour = lt->tm_hour;
00921         now->min  = lt->tm_min;
00922         now->sec  = lt->tm_sec;
00923     }
00924 
00925     return( ret );
00926 }
00927 
00928 /*
00929  * Return 0 if before <= after, 1 otherwise
00930  */
00931 static int x509_check_time( const mbedtls_x509_time *before, const mbedtls_x509_time *after )
00932 {
00933     if( before->year  > after->year )
00934         return( 1 );
00935 
00936     if( before->year == after->year &&
00937         before->mon   > after->mon )
00938         return( 1 );
00939 
00940     if( before->year == after->year &&
00941         before->mon  == after->mon  &&
00942         before->day   > after->day )
00943         return( 1 );
00944 
00945     if( before->year == after->year &&
00946         before->mon  == after->mon  &&
00947         before->day  == after->day  &&
00948         before->hour  > after->hour )
00949         return( 1 );
00950 
00951     if( before->year == after->year &&
00952         before->mon  == after->mon  &&
00953         before->day  == after->day  &&
00954         before->hour == after->hour &&
00955         before->min   > after->min  )
00956         return( 1 );
00957 
00958     if( before->year == after->year &&
00959         before->mon  == after->mon  &&
00960         before->day  == after->day  &&
00961         before->hour == after->hour &&
00962         before->min  == after->min  &&
00963         before->sec   > after->sec  )
00964         return( 1 );
00965 
00966     return( 0 );
00967 }
00968 
00969 int mbedtls_x509_time_is_past( const mbedtls_x509_time *to )
00970 {
00971     mbedtls_x509_time now;
00972 
00973     if( x509_get_current_time( &now ) != 0 )
00974         return( 1 );
00975 
00976     return( x509_check_time( &now, to ) );
00977 }
00978 
00979 int mbedtls_x509_time_is_future( const mbedtls_x509_time *from )
00980 {
00981     mbedtls_x509_time now;
00982 
00983     if( x509_get_current_time( &now ) != 0 )
00984         return( 1 );
00985 
00986     return( x509_check_time( from, &now ) );
00987 }
00988 
00989 #else  /* MBEDTLS_HAVE_TIME_DATE */
00990 
00991 int mbedtls_x509_time_is_past( const mbedtls_x509_time *to )
00992 {
00993     ((void) to);
00994     return( 0 );
00995 }
00996 
00997 int mbedtls_x509_time_is_future( const mbedtls_x509_time *from )
00998 {
00999     ((void) from);
01000     return( 0 );
01001 }
01002 #endif /* MBEDTLS_HAVE_TIME_DATE */
01003 
01004 #if defined(MBEDTLS_SELF_TEST)
01005 
01006 #include "mbedtls/x509_crt.h"
01007 #include "mbedtls/certs.h"
01008 
01009 /*
01010  * Checkup routine
01011  */
01012 int mbedtls_x509_self_test( int verbose )
01013 {
01014     int ret = 0;
01015 #if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_SHA256_C)
01016     uint32_t flags;
01017     mbedtls_x509_crt cacert;
01018     mbedtls_x509_crt clicert;
01019 
01020     if( verbose != 0 )
01021         mbedtls_printf( "  X.509 certificate load: " );
01022 
01023     mbedtls_x509_crt_init( &cacert );
01024     mbedtls_x509_crt_init( &clicert );
01025 
01026     ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) mbedtls_test_cli_crt,
01027                            mbedtls_test_cli_crt_len );
01028     if( ret != 0 )
01029     {
01030         if( verbose != 0 )
01031             mbedtls_printf( "failed\n" );
01032 
01033         goto cleanup;
01034     }
01035 
01036     ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_ca_crt,
01037                           mbedtls_test_ca_crt_len );
01038     if( ret != 0 )
01039     {
01040         if( verbose != 0 )
01041             mbedtls_printf( "failed\n" );
01042 
01043         goto cleanup;
01044     }
01045 
01046     if( verbose != 0 )
01047         mbedtls_printf( "passed\n  X.509 signature verify: ");
01048 
01049     ret = mbedtls_x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL );
01050     if( ret != 0 )
01051     {
01052         if( verbose != 0 )
01053             mbedtls_printf( "failed\n" );
01054 
01055         goto cleanup;
01056     }
01057 
01058     if( verbose != 0 )
01059         mbedtls_printf( "passed\n\n");
01060 
01061 cleanup:
01062     mbedtls_x509_crt_free( &cacert  );
01063     mbedtls_x509_crt_free( &clicert );
01064 #else
01065     ((void) verbose);
01066 #endif /* MBEDTLS_CERTS_C && MBEDTLS_SHA1_C */
01067     return( ret );
01068 }
01069 
01070 #endif /* MBEDTLS_SELF_TEST */
01071 
01072 #endif /* MBEDTLS_X509_USE_C */