Kenji Arai / TYBLE16_mbedlized_os5_several_examples_1st

Dependencies:   nRF51_Vdd TextLCD BME280

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