1*817466cbSJens Wiklander /* 2*817466cbSJens Wiklander * X.509 common functions for parsing and verification 3*817466cbSJens Wiklander * 4*817466cbSJens Wiklander * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 5*817466cbSJens Wiklander * SPDX-License-Identifier: Apache-2.0 6*817466cbSJens Wiklander * 7*817466cbSJens Wiklander * Licensed under the Apache License, Version 2.0 (the "License"); you may 8*817466cbSJens Wiklander * not use this file except in compliance with the License. 9*817466cbSJens Wiklander * You may obtain a copy of the License at 10*817466cbSJens Wiklander * 11*817466cbSJens Wiklander * http://www.apache.org/licenses/LICENSE-2.0 12*817466cbSJens Wiklander * 13*817466cbSJens Wiklander * Unless required by applicable law or agreed to in writing, software 14*817466cbSJens Wiklander * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15*817466cbSJens Wiklander * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16*817466cbSJens Wiklander * See the License for the specific language governing permissions and 17*817466cbSJens Wiklander * limitations under the License. 18*817466cbSJens Wiklander * 19*817466cbSJens Wiklander * This file is part of mbed TLS (https://tls.mbed.org) 20*817466cbSJens Wiklander */ 21*817466cbSJens Wiklander /* 22*817466cbSJens Wiklander * The ITU-T X.509 standard defines a certificate format for PKI. 23*817466cbSJens Wiklander * 24*817466cbSJens Wiklander * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) 25*817466cbSJens Wiklander * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) 26*817466cbSJens Wiklander * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) 27*817466cbSJens Wiklander * 28*817466cbSJens Wiklander * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf 29*817466cbSJens Wiklander * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf 30*817466cbSJens Wiklander */ 31*817466cbSJens Wiklander 32*817466cbSJens Wiklander #if !defined(MBEDTLS_CONFIG_FILE) 33*817466cbSJens Wiklander #include "mbedtls/config.h" 34*817466cbSJens Wiklander #else 35*817466cbSJens Wiklander #include MBEDTLS_CONFIG_FILE 36*817466cbSJens Wiklander #endif 37*817466cbSJens Wiklander 38*817466cbSJens Wiklander #if defined(MBEDTLS_X509_USE_C) 39*817466cbSJens Wiklander 40*817466cbSJens Wiklander #include "mbedtls/x509.h" 41*817466cbSJens Wiklander #include "mbedtls/asn1.h" 42*817466cbSJens Wiklander #include "mbedtls/oid.h" 43*817466cbSJens Wiklander 44*817466cbSJens Wiklander #include <stdio.h> 45*817466cbSJens Wiklander #include <string.h> 46*817466cbSJens Wiklander 47*817466cbSJens Wiklander #if defined(MBEDTLS_PEM_PARSE_C) 48*817466cbSJens Wiklander #include "mbedtls/pem.h" 49*817466cbSJens Wiklander #endif 50*817466cbSJens Wiklander 51*817466cbSJens Wiklander #if defined(MBEDTLS_PLATFORM_C) 52*817466cbSJens Wiklander #include "mbedtls/platform.h" 53*817466cbSJens Wiklander #else 54*817466cbSJens Wiklander #include <stdio.h> 55*817466cbSJens Wiklander #include <stdlib.h> 56*817466cbSJens Wiklander #define mbedtls_free free 57*817466cbSJens Wiklander #define mbedtls_calloc calloc 58*817466cbSJens Wiklander #define mbedtls_printf printf 59*817466cbSJens Wiklander #define mbedtls_snprintf snprintf 60*817466cbSJens Wiklander #endif 61*817466cbSJens Wiklander 62*817466cbSJens Wiklander 63*817466cbSJens Wiklander #if defined(MBEDTLS_HAVE_TIME) 64*817466cbSJens Wiklander #include "mbedtls/platform_time.h" 65*817466cbSJens Wiklander #endif 66*817466cbSJens Wiklander 67*817466cbSJens Wiklander #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) 68*817466cbSJens Wiklander #include <windows.h> 69*817466cbSJens Wiklander #else 70*817466cbSJens Wiklander #include <time.h> 71*817466cbSJens Wiklander #endif 72*817466cbSJens Wiklander 73*817466cbSJens Wiklander #if defined(MBEDTLS_FS_IO) 74*817466cbSJens Wiklander #include <stdio.h> 75*817466cbSJens Wiklander #if !defined(_WIN32) 76*817466cbSJens Wiklander #include <sys/types.h> 77*817466cbSJens Wiklander #include <sys/stat.h> 78*817466cbSJens Wiklander #include <dirent.h> 79*817466cbSJens Wiklander #endif 80*817466cbSJens Wiklander #endif 81*817466cbSJens Wiklander 82*817466cbSJens Wiklander #define CHECK(code) if( ( ret = code ) != 0 ){ return( ret ); } 83*817466cbSJens Wiklander #define CHECK_RANGE(min, max, val) if( val < min || val > max ){ return( ret ); } 84*817466cbSJens Wiklander 85*817466cbSJens Wiklander /* 86*817466cbSJens Wiklander * CertificateSerialNumber ::= INTEGER 87*817466cbSJens Wiklander */ 88*817466cbSJens Wiklander int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end, 89*817466cbSJens Wiklander mbedtls_x509_buf *serial ) 90*817466cbSJens Wiklander { 91*817466cbSJens Wiklander int ret; 92*817466cbSJens Wiklander 93*817466cbSJens Wiklander if( ( end - *p ) < 1 ) 94*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_SERIAL + 95*817466cbSJens Wiklander MBEDTLS_ERR_ASN1_OUT_OF_DATA ); 96*817466cbSJens Wiklander 97*817466cbSJens Wiklander if( **p != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2 ) && 98*817466cbSJens Wiklander **p != MBEDTLS_ASN1_INTEGER ) 99*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_SERIAL + 100*817466cbSJens Wiklander MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); 101*817466cbSJens Wiklander 102*817466cbSJens Wiklander serial->tag = *(*p)++; 103*817466cbSJens Wiklander 104*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_len( p, end, &serial->len ) ) != 0 ) 105*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_SERIAL + ret ); 106*817466cbSJens Wiklander 107*817466cbSJens Wiklander serial->p = *p; 108*817466cbSJens Wiklander *p += serial->len; 109*817466cbSJens Wiklander 110*817466cbSJens Wiklander return( 0 ); 111*817466cbSJens Wiklander } 112*817466cbSJens Wiklander 113*817466cbSJens Wiklander /* Get an algorithm identifier without parameters (eg for signatures) 114*817466cbSJens Wiklander * 115*817466cbSJens Wiklander * AlgorithmIdentifier ::= SEQUENCE { 116*817466cbSJens Wiklander * algorithm OBJECT IDENTIFIER, 117*817466cbSJens Wiklander * parameters ANY DEFINED BY algorithm OPTIONAL } 118*817466cbSJens Wiklander */ 119*817466cbSJens Wiklander int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end, 120*817466cbSJens Wiklander mbedtls_x509_buf *alg ) 121*817466cbSJens Wiklander { 122*817466cbSJens Wiklander int ret; 123*817466cbSJens Wiklander 124*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 ) 125*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); 126*817466cbSJens Wiklander 127*817466cbSJens Wiklander return( 0 ); 128*817466cbSJens Wiklander } 129*817466cbSJens Wiklander 130*817466cbSJens Wiklander /* 131*817466cbSJens Wiklander * Parse an algorithm identifier with (optional) paramaters 132*817466cbSJens Wiklander */ 133*817466cbSJens Wiklander int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end, 134*817466cbSJens Wiklander mbedtls_x509_buf *alg, mbedtls_x509_buf *params ) 135*817466cbSJens Wiklander { 136*817466cbSJens Wiklander int ret; 137*817466cbSJens Wiklander 138*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_alg( p, end, alg, params ) ) != 0 ) 139*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); 140*817466cbSJens Wiklander 141*817466cbSJens Wiklander return( 0 ); 142*817466cbSJens Wiklander } 143*817466cbSJens Wiklander 144*817466cbSJens Wiklander #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) 145*817466cbSJens Wiklander /* 146*817466cbSJens Wiklander * HashAlgorithm ::= AlgorithmIdentifier 147*817466cbSJens Wiklander * 148*817466cbSJens Wiklander * AlgorithmIdentifier ::= SEQUENCE { 149*817466cbSJens Wiklander * algorithm OBJECT IDENTIFIER, 150*817466cbSJens Wiklander * parameters ANY DEFINED BY algorithm OPTIONAL } 151*817466cbSJens Wiklander * 152*817466cbSJens Wiklander * For HashAlgorithm, parameters MUST be NULL or absent. 153*817466cbSJens Wiklander */ 154*817466cbSJens Wiklander static int x509_get_hash_alg( const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg ) 155*817466cbSJens Wiklander { 156*817466cbSJens Wiklander int ret; 157*817466cbSJens Wiklander unsigned char *p; 158*817466cbSJens Wiklander const unsigned char *end; 159*817466cbSJens Wiklander mbedtls_x509_buf md_oid; 160*817466cbSJens Wiklander size_t len; 161*817466cbSJens Wiklander 162*817466cbSJens Wiklander /* Make sure we got a SEQUENCE and setup bounds */ 163*817466cbSJens Wiklander if( alg->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) 164*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_ALG + 165*817466cbSJens Wiklander MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); 166*817466cbSJens Wiklander 167*817466cbSJens Wiklander p = (unsigned char *) alg->p; 168*817466cbSJens Wiklander end = p + alg->len; 169*817466cbSJens Wiklander 170*817466cbSJens Wiklander if( p >= end ) 171*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_ALG + 172*817466cbSJens Wiklander MBEDTLS_ERR_ASN1_OUT_OF_DATA ); 173*817466cbSJens Wiklander 174*817466cbSJens Wiklander /* Parse md_oid */ 175*817466cbSJens Wiklander md_oid.tag = *p; 176*817466cbSJens Wiklander 177*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &md_oid.len, MBEDTLS_ASN1_OID ) ) != 0 ) 178*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); 179*817466cbSJens Wiklander 180*817466cbSJens Wiklander md_oid.p = p; 181*817466cbSJens Wiklander p += md_oid.len; 182*817466cbSJens Wiklander 183*817466cbSJens Wiklander /* Get md_alg from md_oid */ 184*817466cbSJens Wiklander if( ( ret = mbedtls_oid_get_md_alg( &md_oid, md_alg ) ) != 0 ) 185*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); 186*817466cbSJens Wiklander 187*817466cbSJens Wiklander /* Make sure params is absent of NULL */ 188*817466cbSJens Wiklander if( p == end ) 189*817466cbSJens Wiklander return( 0 ); 190*817466cbSJens Wiklander 191*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_NULL ) ) != 0 || len != 0 ) 192*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); 193*817466cbSJens Wiklander 194*817466cbSJens Wiklander if( p != end ) 195*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_ALG + 196*817466cbSJens Wiklander MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); 197*817466cbSJens Wiklander 198*817466cbSJens Wiklander return( 0 ); 199*817466cbSJens Wiklander } 200*817466cbSJens Wiklander 201*817466cbSJens Wiklander /* 202*817466cbSJens Wiklander * RSASSA-PSS-params ::= SEQUENCE { 203*817466cbSJens Wiklander * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier, 204*817466cbSJens Wiklander * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier, 205*817466cbSJens Wiklander * saltLength [2] INTEGER DEFAULT 20, 206*817466cbSJens Wiklander * trailerField [3] INTEGER DEFAULT 1 } 207*817466cbSJens Wiklander * -- Note that the tags in this Sequence are explicit. 208*817466cbSJens Wiklander * 209*817466cbSJens Wiklander * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value 210*817466cbSJens Wiklander * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other 211*817466cbSJens Wiklander * option. Enfore this at parsing time. 212*817466cbSJens Wiklander */ 213*817466cbSJens Wiklander int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params, 214*817466cbSJens Wiklander mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, 215*817466cbSJens Wiklander int *salt_len ) 216*817466cbSJens Wiklander { 217*817466cbSJens Wiklander int ret; 218*817466cbSJens Wiklander unsigned char *p; 219*817466cbSJens Wiklander const unsigned char *end, *end2; 220*817466cbSJens Wiklander size_t len; 221*817466cbSJens Wiklander mbedtls_x509_buf alg_id, alg_params; 222*817466cbSJens Wiklander 223*817466cbSJens Wiklander /* First set everything to defaults */ 224*817466cbSJens Wiklander *md_alg = MBEDTLS_MD_SHA1; 225*817466cbSJens Wiklander *mgf_md = MBEDTLS_MD_SHA1; 226*817466cbSJens Wiklander *salt_len = 20; 227*817466cbSJens Wiklander 228*817466cbSJens Wiklander /* Make sure params is a SEQUENCE and setup bounds */ 229*817466cbSJens Wiklander if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) 230*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_ALG + 231*817466cbSJens Wiklander MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); 232*817466cbSJens Wiklander 233*817466cbSJens Wiklander p = (unsigned char *) params->p; 234*817466cbSJens Wiklander end = p + params->len; 235*817466cbSJens Wiklander 236*817466cbSJens Wiklander if( p == end ) 237*817466cbSJens Wiklander return( 0 ); 238*817466cbSJens Wiklander 239*817466cbSJens Wiklander /* 240*817466cbSJens Wiklander * HashAlgorithm 241*817466cbSJens Wiklander */ 242*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, 243*817466cbSJens Wiklander MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 ) 244*817466cbSJens Wiklander { 245*817466cbSJens Wiklander end2 = p + len; 246*817466cbSJens Wiklander 247*817466cbSJens Wiklander /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */ 248*817466cbSJens Wiklander if( ( ret = mbedtls_x509_get_alg_null( &p, end2, &alg_id ) ) != 0 ) 249*817466cbSJens Wiklander return( ret ); 250*817466cbSJens Wiklander 251*817466cbSJens Wiklander if( ( ret = mbedtls_oid_get_md_alg( &alg_id, md_alg ) ) != 0 ) 252*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); 253*817466cbSJens Wiklander 254*817466cbSJens Wiklander if( p != end2 ) 255*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_ALG + 256*817466cbSJens Wiklander MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); 257*817466cbSJens Wiklander } 258*817466cbSJens Wiklander else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) 259*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); 260*817466cbSJens Wiklander 261*817466cbSJens Wiklander if( p == end ) 262*817466cbSJens Wiklander return( 0 ); 263*817466cbSJens Wiklander 264*817466cbSJens Wiklander /* 265*817466cbSJens Wiklander * MaskGenAlgorithm 266*817466cbSJens Wiklander */ 267*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, 268*817466cbSJens Wiklander MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 ) 269*817466cbSJens Wiklander { 270*817466cbSJens Wiklander end2 = p + len; 271*817466cbSJens Wiklander 272*817466cbSJens Wiklander /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */ 273*817466cbSJens Wiklander if( ( ret = mbedtls_x509_get_alg( &p, end2, &alg_id, &alg_params ) ) != 0 ) 274*817466cbSJens Wiklander return( ret ); 275*817466cbSJens Wiklander 276*817466cbSJens Wiklander /* Only MFG1 is recognised for now */ 277*817466cbSJens Wiklander if( MBEDTLS_OID_CMP( MBEDTLS_OID_MGF1, &alg_id ) != 0 ) 278*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE + 279*817466cbSJens Wiklander MBEDTLS_ERR_OID_NOT_FOUND ); 280*817466cbSJens Wiklander 281*817466cbSJens Wiklander /* Parse HashAlgorithm */ 282*817466cbSJens Wiklander if( ( ret = x509_get_hash_alg( &alg_params, mgf_md ) ) != 0 ) 283*817466cbSJens Wiklander return( ret ); 284*817466cbSJens Wiklander 285*817466cbSJens Wiklander if( p != end2 ) 286*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_ALG + 287*817466cbSJens Wiklander MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); 288*817466cbSJens Wiklander } 289*817466cbSJens Wiklander else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) 290*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); 291*817466cbSJens Wiklander 292*817466cbSJens Wiklander if( p == end ) 293*817466cbSJens Wiklander return( 0 ); 294*817466cbSJens Wiklander 295*817466cbSJens Wiklander /* 296*817466cbSJens Wiklander * salt_len 297*817466cbSJens Wiklander */ 298*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, 299*817466cbSJens Wiklander MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 2 ) ) == 0 ) 300*817466cbSJens Wiklander { 301*817466cbSJens Wiklander end2 = p + len; 302*817466cbSJens Wiklander 303*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_int( &p, end2, salt_len ) ) != 0 ) 304*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); 305*817466cbSJens Wiklander 306*817466cbSJens Wiklander if( p != end2 ) 307*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_ALG + 308*817466cbSJens Wiklander MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); 309*817466cbSJens Wiklander } 310*817466cbSJens Wiklander else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) 311*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); 312*817466cbSJens Wiklander 313*817466cbSJens Wiklander if( p == end ) 314*817466cbSJens Wiklander return( 0 ); 315*817466cbSJens Wiklander 316*817466cbSJens Wiklander /* 317*817466cbSJens Wiklander * trailer_field (if present, must be 1) 318*817466cbSJens Wiklander */ 319*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, 320*817466cbSJens Wiklander MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 3 ) ) == 0 ) 321*817466cbSJens Wiklander { 322*817466cbSJens Wiklander int trailer_field; 323*817466cbSJens Wiklander 324*817466cbSJens Wiklander end2 = p + len; 325*817466cbSJens Wiklander 326*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_int( &p, end2, &trailer_field ) ) != 0 ) 327*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); 328*817466cbSJens Wiklander 329*817466cbSJens Wiklander if( p != end2 ) 330*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_ALG + 331*817466cbSJens Wiklander MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); 332*817466cbSJens Wiklander 333*817466cbSJens Wiklander if( trailer_field != 1 ) 334*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_ALG ); 335*817466cbSJens Wiklander } 336*817466cbSJens Wiklander else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) 337*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); 338*817466cbSJens Wiklander 339*817466cbSJens Wiklander if( p != end ) 340*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_ALG + 341*817466cbSJens Wiklander MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); 342*817466cbSJens Wiklander 343*817466cbSJens Wiklander return( 0 ); 344*817466cbSJens Wiklander } 345*817466cbSJens Wiklander #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ 346*817466cbSJens Wiklander 347*817466cbSJens Wiklander /* 348*817466cbSJens Wiklander * AttributeTypeAndValue ::= SEQUENCE { 349*817466cbSJens Wiklander * type AttributeType, 350*817466cbSJens Wiklander * value AttributeValue } 351*817466cbSJens Wiklander * 352*817466cbSJens Wiklander * AttributeType ::= OBJECT IDENTIFIER 353*817466cbSJens Wiklander * 354*817466cbSJens Wiklander * AttributeValue ::= ANY DEFINED BY AttributeType 355*817466cbSJens Wiklander */ 356*817466cbSJens Wiklander static int x509_get_attr_type_value( unsigned char **p, 357*817466cbSJens Wiklander const unsigned char *end, 358*817466cbSJens Wiklander mbedtls_x509_name *cur ) 359*817466cbSJens Wiklander { 360*817466cbSJens Wiklander int ret; 361*817466cbSJens Wiklander size_t len; 362*817466cbSJens Wiklander mbedtls_x509_buf *oid; 363*817466cbSJens Wiklander mbedtls_x509_buf *val; 364*817466cbSJens Wiklander 365*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( p, end, &len, 366*817466cbSJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) 367*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); 368*817466cbSJens Wiklander 369*817466cbSJens Wiklander if( ( end - *p ) < 1 ) 370*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_NAME + 371*817466cbSJens Wiklander MBEDTLS_ERR_ASN1_OUT_OF_DATA ); 372*817466cbSJens Wiklander 373*817466cbSJens Wiklander oid = &cur->oid; 374*817466cbSJens Wiklander oid->tag = **p; 375*817466cbSJens Wiklander 376*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( p, end, &oid->len, MBEDTLS_ASN1_OID ) ) != 0 ) 377*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); 378*817466cbSJens Wiklander 379*817466cbSJens Wiklander oid->p = *p; 380*817466cbSJens Wiklander *p += oid->len; 381*817466cbSJens Wiklander 382*817466cbSJens Wiklander if( ( end - *p ) < 1 ) 383*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_NAME + 384*817466cbSJens Wiklander MBEDTLS_ERR_ASN1_OUT_OF_DATA ); 385*817466cbSJens Wiklander 386*817466cbSJens Wiklander if( **p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING && 387*817466cbSJens Wiklander **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING && 388*817466cbSJens Wiklander **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING && 389*817466cbSJens Wiklander **p != MBEDTLS_ASN1_BIT_STRING ) 390*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_NAME + 391*817466cbSJens Wiklander MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); 392*817466cbSJens Wiklander 393*817466cbSJens Wiklander val = &cur->val; 394*817466cbSJens Wiklander val->tag = *(*p)++; 395*817466cbSJens Wiklander 396*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_len( p, end, &val->len ) ) != 0 ) 397*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); 398*817466cbSJens Wiklander 399*817466cbSJens Wiklander val->p = *p; 400*817466cbSJens Wiklander *p += val->len; 401*817466cbSJens Wiklander 402*817466cbSJens Wiklander cur->next = NULL; 403*817466cbSJens Wiklander 404*817466cbSJens Wiklander return( 0 ); 405*817466cbSJens Wiklander } 406*817466cbSJens Wiklander 407*817466cbSJens Wiklander /* 408*817466cbSJens Wiklander * Name ::= CHOICE { -- only one possibility for now -- 409*817466cbSJens Wiklander * rdnSequence RDNSequence } 410*817466cbSJens Wiklander * 411*817466cbSJens Wiklander * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName 412*817466cbSJens Wiklander * 413*817466cbSJens Wiklander * RelativeDistinguishedName ::= 414*817466cbSJens Wiklander * SET OF AttributeTypeAndValue 415*817466cbSJens Wiklander * 416*817466cbSJens Wiklander * AttributeTypeAndValue ::= SEQUENCE { 417*817466cbSJens Wiklander * type AttributeType, 418*817466cbSJens Wiklander * value AttributeValue } 419*817466cbSJens Wiklander * 420*817466cbSJens Wiklander * AttributeType ::= OBJECT IDENTIFIER 421*817466cbSJens Wiklander * 422*817466cbSJens Wiklander * AttributeValue ::= ANY DEFINED BY AttributeType 423*817466cbSJens Wiklander * 424*817466cbSJens Wiklander * The data structure is optimized for the common case where each RDN has only 425*817466cbSJens Wiklander * one element, which is represented as a list of AttributeTypeAndValue. 426*817466cbSJens Wiklander * For the general case we still use a flat list, but we mark elements of the 427*817466cbSJens Wiklander * same set so that they are "merged" together in the functions that consume 428*817466cbSJens Wiklander * this list, eg mbedtls_x509_dn_gets(). 429*817466cbSJens Wiklander */ 430*817466cbSJens Wiklander int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end, 431*817466cbSJens Wiklander mbedtls_x509_name *cur ) 432*817466cbSJens Wiklander { 433*817466cbSJens Wiklander int ret; 434*817466cbSJens Wiklander size_t set_len; 435*817466cbSJens Wiklander const unsigned char *end_set; 436*817466cbSJens Wiklander 437*817466cbSJens Wiklander /* don't use recursion, we'd risk stack overflow if not optimized */ 438*817466cbSJens Wiklander while( 1 ) 439*817466cbSJens Wiklander { 440*817466cbSJens Wiklander /* 441*817466cbSJens Wiklander * parse SET 442*817466cbSJens Wiklander */ 443*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( p, end, &set_len, 444*817466cbSJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ) != 0 ) 445*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); 446*817466cbSJens Wiklander 447*817466cbSJens Wiklander end_set = *p + set_len; 448*817466cbSJens Wiklander 449*817466cbSJens Wiklander while( 1 ) 450*817466cbSJens Wiklander { 451*817466cbSJens Wiklander if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 ) 452*817466cbSJens Wiklander return( ret ); 453*817466cbSJens Wiklander 454*817466cbSJens Wiklander if( *p == end_set ) 455*817466cbSJens Wiklander break; 456*817466cbSJens Wiklander 457*817466cbSJens Wiklander /* Mark this item as being no the only one in a set */ 458*817466cbSJens Wiklander cur->next_merged = 1; 459*817466cbSJens Wiklander 460*817466cbSJens Wiklander cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) ); 461*817466cbSJens Wiklander 462*817466cbSJens Wiklander if( cur->next == NULL ) 463*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_ALLOC_FAILED ); 464*817466cbSJens Wiklander 465*817466cbSJens Wiklander cur = cur->next; 466*817466cbSJens Wiklander } 467*817466cbSJens Wiklander 468*817466cbSJens Wiklander /* 469*817466cbSJens Wiklander * continue until end of SEQUENCE is reached 470*817466cbSJens Wiklander */ 471*817466cbSJens Wiklander if( *p == end ) 472*817466cbSJens Wiklander return( 0 ); 473*817466cbSJens Wiklander 474*817466cbSJens Wiklander cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) ); 475*817466cbSJens Wiklander 476*817466cbSJens Wiklander if( cur->next == NULL ) 477*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_ALLOC_FAILED ); 478*817466cbSJens Wiklander 479*817466cbSJens Wiklander cur = cur->next; 480*817466cbSJens Wiklander } 481*817466cbSJens Wiklander } 482*817466cbSJens Wiklander 483*817466cbSJens Wiklander static int x509_parse_int( unsigned char **p, size_t n, int *res ) 484*817466cbSJens Wiklander { 485*817466cbSJens Wiklander *res = 0; 486*817466cbSJens Wiklander 487*817466cbSJens Wiklander for( ; n > 0; --n ) 488*817466cbSJens Wiklander { 489*817466cbSJens Wiklander if( ( **p < '0') || ( **p > '9' ) ) 490*817466cbSJens Wiklander return ( MBEDTLS_ERR_X509_INVALID_DATE ); 491*817466cbSJens Wiklander 492*817466cbSJens Wiklander *res *= 10; 493*817466cbSJens Wiklander *res += ( *(*p)++ - '0' ); 494*817466cbSJens Wiklander } 495*817466cbSJens Wiklander 496*817466cbSJens Wiklander return( 0 ); 497*817466cbSJens Wiklander } 498*817466cbSJens Wiklander 499*817466cbSJens Wiklander static int x509_date_is_valid(const mbedtls_x509_time *t) 500*817466cbSJens Wiklander { 501*817466cbSJens Wiklander int ret = MBEDTLS_ERR_X509_INVALID_DATE; 502*817466cbSJens Wiklander 503*817466cbSJens Wiklander CHECK_RANGE( 0, 9999, t->year ); 504*817466cbSJens Wiklander CHECK_RANGE( 0, 23, t->hour ); 505*817466cbSJens Wiklander CHECK_RANGE( 0, 59, t->min ); 506*817466cbSJens Wiklander CHECK_RANGE( 0, 59, t->sec ); 507*817466cbSJens Wiklander 508*817466cbSJens Wiklander switch( t->mon ) 509*817466cbSJens Wiklander { 510*817466cbSJens Wiklander case 1: case 3: case 5: case 7: case 8: case 10: case 12: 511*817466cbSJens Wiklander CHECK_RANGE( 1, 31, t->day ); 512*817466cbSJens Wiklander break; 513*817466cbSJens Wiklander case 4: case 6: case 9: case 11: 514*817466cbSJens Wiklander CHECK_RANGE( 1, 30, t->day ); 515*817466cbSJens Wiklander break; 516*817466cbSJens Wiklander case 2: 517*817466cbSJens Wiklander CHECK_RANGE( 1, 28 + (t->year % 4 == 0), t->day ); 518*817466cbSJens Wiklander break; 519*817466cbSJens Wiklander default: 520*817466cbSJens Wiklander return( ret ); 521*817466cbSJens Wiklander } 522*817466cbSJens Wiklander 523*817466cbSJens Wiklander return( 0 ); 524*817466cbSJens Wiklander } 525*817466cbSJens Wiklander 526*817466cbSJens Wiklander /* 527*817466cbSJens Wiklander * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4) 528*817466cbSJens Wiklander * field. 529*817466cbSJens Wiklander */ 530*817466cbSJens Wiklander static int x509_parse_time( unsigned char **p, size_t len, size_t yearlen, 531*817466cbSJens Wiklander mbedtls_x509_time *tm ) 532*817466cbSJens Wiklander { 533*817466cbSJens Wiklander int ret; 534*817466cbSJens Wiklander 535*817466cbSJens Wiklander /* 536*817466cbSJens Wiklander * Minimum length is 10 or 12 depending on yearlen 537*817466cbSJens Wiklander */ 538*817466cbSJens Wiklander if ( len < yearlen + 8 ) 539*817466cbSJens Wiklander return ( MBEDTLS_ERR_X509_INVALID_DATE ); 540*817466cbSJens Wiklander len -= yearlen + 8; 541*817466cbSJens Wiklander 542*817466cbSJens Wiklander /* 543*817466cbSJens Wiklander * Parse year, month, day, hour, minute 544*817466cbSJens Wiklander */ 545*817466cbSJens Wiklander CHECK( x509_parse_int( p, yearlen, &tm->year ) ); 546*817466cbSJens Wiklander if ( 2 == yearlen ) 547*817466cbSJens Wiklander { 548*817466cbSJens Wiklander if ( tm->year < 50 ) 549*817466cbSJens Wiklander tm->year += 100; 550*817466cbSJens Wiklander 551*817466cbSJens Wiklander tm->year += 1900; 552*817466cbSJens Wiklander } 553*817466cbSJens Wiklander 554*817466cbSJens Wiklander CHECK( x509_parse_int( p, 2, &tm->mon ) ); 555*817466cbSJens Wiklander CHECK( x509_parse_int( p, 2, &tm->day ) ); 556*817466cbSJens Wiklander CHECK( x509_parse_int( p, 2, &tm->hour ) ); 557*817466cbSJens Wiklander CHECK( x509_parse_int( p, 2, &tm->min ) ); 558*817466cbSJens Wiklander 559*817466cbSJens Wiklander /* 560*817466cbSJens Wiklander * Parse seconds if present 561*817466cbSJens Wiklander */ 562*817466cbSJens Wiklander if ( len >= 2 ) 563*817466cbSJens Wiklander { 564*817466cbSJens Wiklander CHECK( x509_parse_int( p, 2, &tm->sec ) ); 565*817466cbSJens Wiklander len -= 2; 566*817466cbSJens Wiklander } 567*817466cbSJens Wiklander else 568*817466cbSJens Wiklander return ( MBEDTLS_ERR_X509_INVALID_DATE ); 569*817466cbSJens Wiklander 570*817466cbSJens Wiklander /* 571*817466cbSJens Wiklander * Parse trailing 'Z' if present 572*817466cbSJens Wiklander */ 573*817466cbSJens Wiklander if ( 1 == len && 'Z' == **p ) 574*817466cbSJens Wiklander { 575*817466cbSJens Wiklander (*p)++; 576*817466cbSJens Wiklander len--; 577*817466cbSJens Wiklander } 578*817466cbSJens Wiklander 579*817466cbSJens Wiklander /* 580*817466cbSJens Wiklander * We should have parsed all characters at this point 581*817466cbSJens Wiklander */ 582*817466cbSJens Wiklander if ( 0 != len ) 583*817466cbSJens Wiklander return ( MBEDTLS_ERR_X509_INVALID_DATE ); 584*817466cbSJens Wiklander 585*817466cbSJens Wiklander CHECK( x509_date_is_valid( tm ) ); 586*817466cbSJens Wiklander 587*817466cbSJens Wiklander return ( 0 ); 588*817466cbSJens Wiklander } 589*817466cbSJens Wiklander 590*817466cbSJens Wiklander /* 591*817466cbSJens Wiklander * Time ::= CHOICE { 592*817466cbSJens Wiklander * utcTime UTCTime, 593*817466cbSJens Wiklander * generalTime GeneralizedTime } 594*817466cbSJens Wiklander */ 595*817466cbSJens Wiklander int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, 596*817466cbSJens Wiklander mbedtls_x509_time *tm ) 597*817466cbSJens Wiklander { 598*817466cbSJens Wiklander int ret; 599*817466cbSJens Wiklander size_t len, year_len; 600*817466cbSJens Wiklander unsigned char tag; 601*817466cbSJens Wiklander 602*817466cbSJens Wiklander if( ( end - *p ) < 1 ) 603*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_DATE + 604*817466cbSJens Wiklander MBEDTLS_ERR_ASN1_OUT_OF_DATA ); 605*817466cbSJens Wiklander 606*817466cbSJens Wiklander tag = **p; 607*817466cbSJens Wiklander 608*817466cbSJens Wiklander if( tag == MBEDTLS_ASN1_UTC_TIME ) 609*817466cbSJens Wiklander year_len = 2; 610*817466cbSJens Wiklander else if( tag == MBEDTLS_ASN1_GENERALIZED_TIME ) 611*817466cbSJens Wiklander year_len = 4; 612*817466cbSJens Wiklander else 613*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_DATE + 614*817466cbSJens Wiklander MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); 615*817466cbSJens Wiklander 616*817466cbSJens Wiklander (*p)++; 617*817466cbSJens Wiklander ret = mbedtls_asn1_get_len( p, end, &len ); 618*817466cbSJens Wiklander 619*817466cbSJens Wiklander if( ret != 0 ) 620*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_DATE + ret ); 621*817466cbSJens Wiklander 622*817466cbSJens Wiklander return x509_parse_time( p, len, year_len, tm ); 623*817466cbSJens Wiklander } 624*817466cbSJens Wiklander 625*817466cbSJens Wiklander int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig ) 626*817466cbSJens Wiklander { 627*817466cbSJens Wiklander int ret; 628*817466cbSJens Wiklander size_t len; 629*817466cbSJens Wiklander int tag_type; 630*817466cbSJens Wiklander 631*817466cbSJens Wiklander if( ( end - *p ) < 1 ) 632*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + 633*817466cbSJens Wiklander MBEDTLS_ERR_ASN1_OUT_OF_DATA ); 634*817466cbSJens Wiklander 635*817466cbSJens Wiklander tag_type = **p; 636*817466cbSJens Wiklander 637*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 ) 638*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + ret ); 639*817466cbSJens Wiklander 640*817466cbSJens Wiklander sig->tag = tag_type; 641*817466cbSJens Wiklander sig->len = len; 642*817466cbSJens Wiklander sig->p = *p; 643*817466cbSJens Wiklander 644*817466cbSJens Wiklander *p += len; 645*817466cbSJens Wiklander 646*817466cbSJens Wiklander return( 0 ); 647*817466cbSJens Wiklander } 648*817466cbSJens Wiklander 649*817466cbSJens Wiklander /* 650*817466cbSJens Wiklander * Get signature algorithm from alg OID and optional parameters 651*817466cbSJens Wiklander */ 652*817466cbSJens Wiklander int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, 653*817466cbSJens Wiklander mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, 654*817466cbSJens Wiklander void **sig_opts ) 655*817466cbSJens Wiklander { 656*817466cbSJens Wiklander int ret; 657*817466cbSJens Wiklander 658*817466cbSJens Wiklander if( *sig_opts != NULL ) 659*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); 660*817466cbSJens Wiklander 661*817466cbSJens Wiklander if( ( ret = mbedtls_oid_get_sig_alg( sig_oid, md_alg, pk_alg ) ) != 0 ) 662*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + ret ); 663*817466cbSJens Wiklander 664*817466cbSJens Wiklander #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) 665*817466cbSJens Wiklander if( *pk_alg == MBEDTLS_PK_RSASSA_PSS ) 666*817466cbSJens Wiklander { 667*817466cbSJens Wiklander mbedtls_pk_rsassa_pss_options *pss_opts; 668*817466cbSJens Wiklander 669*817466cbSJens Wiklander pss_opts = mbedtls_calloc( 1, sizeof( mbedtls_pk_rsassa_pss_options ) ); 670*817466cbSJens Wiklander if( pss_opts == NULL ) 671*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_ALLOC_FAILED ); 672*817466cbSJens Wiklander 673*817466cbSJens Wiklander ret = mbedtls_x509_get_rsassa_pss_params( sig_params, 674*817466cbSJens Wiklander md_alg, 675*817466cbSJens Wiklander &pss_opts->mgf1_hash_id, 676*817466cbSJens Wiklander &pss_opts->expected_salt_len ); 677*817466cbSJens Wiklander if( ret != 0 ) 678*817466cbSJens Wiklander { 679*817466cbSJens Wiklander mbedtls_free( pss_opts ); 680*817466cbSJens Wiklander return( ret ); 681*817466cbSJens Wiklander } 682*817466cbSJens Wiklander 683*817466cbSJens Wiklander *sig_opts = (void *) pss_opts; 684*817466cbSJens Wiklander } 685*817466cbSJens Wiklander else 686*817466cbSJens Wiklander #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ 687*817466cbSJens Wiklander { 688*817466cbSJens Wiklander /* Make sure parameters are absent or NULL */ 689*817466cbSJens Wiklander if( ( sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0 ) || 690*817466cbSJens Wiklander sig_params->len != 0 ) 691*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_ALG ); 692*817466cbSJens Wiklander } 693*817466cbSJens Wiklander 694*817466cbSJens Wiklander return( 0 ); 695*817466cbSJens Wiklander } 696*817466cbSJens Wiklander 697*817466cbSJens Wiklander /* 698*817466cbSJens Wiklander * X.509 Extensions (No parsing of extensions, pointer should 699*817466cbSJens Wiklander * be either manually updated or extensions should be parsed!) 700*817466cbSJens Wiklander */ 701*817466cbSJens Wiklander int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end, 702*817466cbSJens Wiklander mbedtls_x509_buf *ext, int tag ) 703*817466cbSJens Wiklander { 704*817466cbSJens Wiklander int ret; 705*817466cbSJens Wiklander size_t len; 706*817466cbSJens Wiklander 707*817466cbSJens Wiklander if( *p == end ) 708*817466cbSJens Wiklander return( 0 ); 709*817466cbSJens Wiklander 710*817466cbSJens Wiklander ext->tag = **p; 711*817466cbSJens Wiklander 712*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( p, end, &ext->len, 713*817466cbSJens Wiklander MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag ) ) != 0 ) 714*817466cbSJens Wiklander return( ret ); 715*817466cbSJens Wiklander 716*817466cbSJens Wiklander ext->p = *p; 717*817466cbSJens Wiklander end = *p + ext->len; 718*817466cbSJens Wiklander 719*817466cbSJens Wiklander /* 720*817466cbSJens Wiklander * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension 721*817466cbSJens Wiklander * 722*817466cbSJens Wiklander * Extension ::= SEQUENCE { 723*817466cbSJens Wiklander * extnID OBJECT IDENTIFIER, 724*817466cbSJens Wiklander * critical BOOLEAN DEFAULT FALSE, 725*817466cbSJens Wiklander * extnValue OCTET STRING } 726*817466cbSJens Wiklander */ 727*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( p, end, &len, 728*817466cbSJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) 729*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); 730*817466cbSJens Wiklander 731*817466cbSJens Wiklander if( end != *p + len ) 732*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + 733*817466cbSJens Wiklander MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); 734*817466cbSJens Wiklander 735*817466cbSJens Wiklander return( 0 ); 736*817466cbSJens Wiklander } 737*817466cbSJens Wiklander 738*817466cbSJens Wiklander /* 739*817466cbSJens Wiklander * Store the name in printable form into buf; no more 740*817466cbSJens Wiklander * than size characters will be written 741*817466cbSJens Wiklander */ 742*817466cbSJens Wiklander int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn ) 743*817466cbSJens Wiklander { 744*817466cbSJens Wiklander int ret; 745*817466cbSJens Wiklander size_t i, n; 746*817466cbSJens Wiklander unsigned char c, merge = 0; 747*817466cbSJens Wiklander const mbedtls_x509_name *name; 748*817466cbSJens Wiklander const char *short_name = NULL; 749*817466cbSJens Wiklander char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p; 750*817466cbSJens Wiklander 751*817466cbSJens Wiklander memset( s, 0, sizeof( s ) ); 752*817466cbSJens Wiklander 753*817466cbSJens Wiklander name = dn; 754*817466cbSJens Wiklander p = buf; 755*817466cbSJens Wiklander n = size; 756*817466cbSJens Wiklander 757*817466cbSJens Wiklander while( name != NULL ) 758*817466cbSJens Wiklander { 759*817466cbSJens Wiklander if( !name->oid.p ) 760*817466cbSJens Wiklander { 761*817466cbSJens Wiklander name = name->next; 762*817466cbSJens Wiklander continue; 763*817466cbSJens Wiklander } 764*817466cbSJens Wiklander 765*817466cbSJens Wiklander if( name != dn ) 766*817466cbSJens Wiklander { 767*817466cbSJens Wiklander ret = mbedtls_snprintf( p, n, merge ? " + " : ", " ); 768*817466cbSJens Wiklander MBEDTLS_X509_SAFE_SNPRINTF; 769*817466cbSJens Wiklander } 770*817466cbSJens Wiklander 771*817466cbSJens Wiklander ret = mbedtls_oid_get_attr_short_name( &name->oid, &short_name ); 772*817466cbSJens Wiklander 773*817466cbSJens Wiklander if( ret == 0 ) 774*817466cbSJens Wiklander ret = mbedtls_snprintf( p, n, "%s=", short_name ); 775*817466cbSJens Wiklander else 776*817466cbSJens Wiklander ret = mbedtls_snprintf( p, n, "\?\?=" ); 777*817466cbSJens Wiklander MBEDTLS_X509_SAFE_SNPRINTF; 778*817466cbSJens Wiklander 779*817466cbSJens Wiklander for( i = 0; i < name->val.len; i++ ) 780*817466cbSJens Wiklander { 781*817466cbSJens Wiklander if( i >= sizeof( s ) - 1 ) 782*817466cbSJens Wiklander break; 783*817466cbSJens Wiklander 784*817466cbSJens Wiklander c = name->val.p[i]; 785*817466cbSJens Wiklander if( c < 32 || c == 127 || ( c > 128 && c < 160 ) ) 786*817466cbSJens Wiklander s[i] = '?'; 787*817466cbSJens Wiklander else s[i] = c; 788*817466cbSJens Wiklander } 789*817466cbSJens Wiklander s[i] = '\0'; 790*817466cbSJens Wiklander ret = mbedtls_snprintf( p, n, "%s", s ); 791*817466cbSJens Wiklander MBEDTLS_X509_SAFE_SNPRINTF; 792*817466cbSJens Wiklander 793*817466cbSJens Wiklander merge = name->next_merged; 794*817466cbSJens Wiklander name = name->next; 795*817466cbSJens Wiklander } 796*817466cbSJens Wiklander 797*817466cbSJens Wiklander return( (int) ( size - n ) ); 798*817466cbSJens Wiklander } 799*817466cbSJens Wiklander 800*817466cbSJens Wiklander /* 801*817466cbSJens Wiklander * Store the serial in printable form into buf; no more 802*817466cbSJens Wiklander * than size characters will be written 803*817466cbSJens Wiklander */ 804*817466cbSJens Wiklander int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial ) 805*817466cbSJens Wiklander { 806*817466cbSJens Wiklander int ret; 807*817466cbSJens Wiklander size_t i, n, nr; 808*817466cbSJens Wiklander char *p; 809*817466cbSJens Wiklander 810*817466cbSJens Wiklander p = buf; 811*817466cbSJens Wiklander n = size; 812*817466cbSJens Wiklander 813*817466cbSJens Wiklander nr = ( serial->len <= 32 ) 814*817466cbSJens Wiklander ? serial->len : 28; 815*817466cbSJens Wiklander 816*817466cbSJens Wiklander for( i = 0; i < nr; i++ ) 817*817466cbSJens Wiklander { 818*817466cbSJens Wiklander if( i == 0 && nr > 1 && serial->p[i] == 0x0 ) 819*817466cbSJens Wiklander continue; 820*817466cbSJens Wiklander 821*817466cbSJens Wiklander ret = mbedtls_snprintf( p, n, "%02X%s", 822*817466cbSJens Wiklander serial->p[i], ( i < nr - 1 ) ? ":" : "" ); 823*817466cbSJens Wiklander MBEDTLS_X509_SAFE_SNPRINTF; 824*817466cbSJens Wiklander } 825*817466cbSJens Wiklander 826*817466cbSJens Wiklander if( nr != serial->len ) 827*817466cbSJens Wiklander { 828*817466cbSJens Wiklander ret = mbedtls_snprintf( p, n, "...." ); 829*817466cbSJens Wiklander MBEDTLS_X509_SAFE_SNPRINTF; 830*817466cbSJens Wiklander } 831*817466cbSJens Wiklander 832*817466cbSJens Wiklander return( (int) ( size - n ) ); 833*817466cbSJens Wiklander } 834*817466cbSJens Wiklander 835*817466cbSJens Wiklander /* 836*817466cbSJens Wiklander * Helper for writing signature algorithms 837*817466cbSJens Wiklander */ 838*817466cbSJens Wiklander int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid, 839*817466cbSJens Wiklander mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, 840*817466cbSJens Wiklander const void *sig_opts ) 841*817466cbSJens Wiklander { 842*817466cbSJens Wiklander int ret; 843*817466cbSJens Wiklander char *p = buf; 844*817466cbSJens Wiklander size_t n = size; 845*817466cbSJens Wiklander const char *desc = NULL; 846*817466cbSJens Wiklander 847*817466cbSJens Wiklander ret = mbedtls_oid_get_sig_alg_desc( sig_oid, &desc ); 848*817466cbSJens Wiklander if( ret != 0 ) 849*817466cbSJens Wiklander ret = mbedtls_snprintf( p, n, "???" ); 850*817466cbSJens Wiklander else 851*817466cbSJens Wiklander ret = mbedtls_snprintf( p, n, "%s", desc ); 852*817466cbSJens Wiklander MBEDTLS_X509_SAFE_SNPRINTF; 853*817466cbSJens Wiklander 854*817466cbSJens Wiklander #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) 855*817466cbSJens Wiklander if( pk_alg == MBEDTLS_PK_RSASSA_PSS ) 856*817466cbSJens Wiklander { 857*817466cbSJens Wiklander const mbedtls_pk_rsassa_pss_options *pss_opts; 858*817466cbSJens Wiklander const mbedtls_md_info_t *md_info, *mgf_md_info; 859*817466cbSJens Wiklander 860*817466cbSJens Wiklander pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts; 861*817466cbSJens Wiklander 862*817466cbSJens Wiklander md_info = mbedtls_md_info_from_type( md_alg ); 863*817466cbSJens Wiklander mgf_md_info = mbedtls_md_info_from_type( pss_opts->mgf1_hash_id ); 864*817466cbSJens Wiklander 865*817466cbSJens Wiklander ret = mbedtls_snprintf( p, n, " (%s, MGF1-%s, 0x%02X)", 866*817466cbSJens Wiklander md_info ? mbedtls_md_get_name( md_info ) : "???", 867*817466cbSJens Wiklander mgf_md_info ? mbedtls_md_get_name( mgf_md_info ) : "???", 868*817466cbSJens Wiklander pss_opts->expected_salt_len ); 869*817466cbSJens Wiklander MBEDTLS_X509_SAFE_SNPRINTF; 870*817466cbSJens Wiklander } 871*817466cbSJens Wiklander #else 872*817466cbSJens Wiklander ((void) pk_alg); 873*817466cbSJens Wiklander ((void) md_alg); 874*817466cbSJens Wiklander ((void) sig_opts); 875*817466cbSJens Wiklander #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ 876*817466cbSJens Wiklander 877*817466cbSJens Wiklander return( (int)( size - n ) ); 878*817466cbSJens Wiklander } 879*817466cbSJens Wiklander 880*817466cbSJens Wiklander /* 881*817466cbSJens Wiklander * Helper for writing "RSA key size", "EC key size", etc 882*817466cbSJens Wiklander */ 883*817466cbSJens Wiklander int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name ) 884*817466cbSJens Wiklander { 885*817466cbSJens Wiklander char *p = buf; 886*817466cbSJens Wiklander size_t n = buf_size; 887*817466cbSJens Wiklander int ret; 888*817466cbSJens Wiklander 889*817466cbSJens Wiklander ret = mbedtls_snprintf( p, n, "%s key size", name ); 890*817466cbSJens Wiklander MBEDTLS_X509_SAFE_SNPRINTF; 891*817466cbSJens Wiklander 892*817466cbSJens Wiklander return( 0 ); 893*817466cbSJens Wiklander } 894*817466cbSJens Wiklander 895*817466cbSJens Wiklander #if defined(MBEDTLS_HAVE_TIME_DATE) 896*817466cbSJens Wiklander /* 897*817466cbSJens Wiklander * Set the time structure to the current time. 898*817466cbSJens Wiklander * Return 0 on success, non-zero on failure. 899*817466cbSJens Wiklander */ 900*817466cbSJens Wiklander #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) 901*817466cbSJens Wiklander static int x509_get_current_time( mbedtls_x509_time *now ) 902*817466cbSJens Wiklander { 903*817466cbSJens Wiklander SYSTEMTIME st; 904*817466cbSJens Wiklander 905*817466cbSJens Wiklander GetSystemTime( &st ); 906*817466cbSJens Wiklander 907*817466cbSJens Wiklander now->year = st.wYear; 908*817466cbSJens Wiklander now->mon = st.wMonth; 909*817466cbSJens Wiklander now->day = st.wDay; 910*817466cbSJens Wiklander now->hour = st.wHour; 911*817466cbSJens Wiklander now->min = st.wMinute; 912*817466cbSJens Wiklander now->sec = st.wSecond; 913*817466cbSJens Wiklander 914*817466cbSJens Wiklander return( 0 ); 915*817466cbSJens Wiklander } 916*817466cbSJens Wiklander #else 917*817466cbSJens Wiklander static int x509_get_current_time( mbedtls_x509_time *now ) 918*817466cbSJens Wiklander { 919*817466cbSJens Wiklander struct tm *lt; 920*817466cbSJens Wiklander mbedtls_time_t tt; 921*817466cbSJens Wiklander int ret = 0; 922*817466cbSJens Wiklander 923*817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C) 924*817466cbSJens Wiklander if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 ) 925*817466cbSJens Wiklander return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); 926*817466cbSJens Wiklander #endif 927*817466cbSJens Wiklander 928*817466cbSJens Wiklander tt = mbedtls_time( NULL ); 929*817466cbSJens Wiklander lt = gmtime( &tt ); 930*817466cbSJens Wiklander 931*817466cbSJens Wiklander if( lt == NULL ) 932*817466cbSJens Wiklander ret = -1; 933*817466cbSJens Wiklander else 934*817466cbSJens Wiklander { 935*817466cbSJens Wiklander now->year = lt->tm_year + 1900; 936*817466cbSJens Wiklander now->mon = lt->tm_mon + 1; 937*817466cbSJens Wiklander now->day = lt->tm_mday; 938*817466cbSJens Wiklander now->hour = lt->tm_hour; 939*817466cbSJens Wiklander now->min = lt->tm_min; 940*817466cbSJens Wiklander now->sec = lt->tm_sec; 941*817466cbSJens Wiklander } 942*817466cbSJens Wiklander 943*817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C) 944*817466cbSJens Wiklander if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 ) 945*817466cbSJens Wiklander return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); 946*817466cbSJens Wiklander #endif 947*817466cbSJens Wiklander 948*817466cbSJens Wiklander return( ret ); 949*817466cbSJens Wiklander } 950*817466cbSJens Wiklander #endif /* _WIN32 && !EFIX64 && !EFI32 */ 951*817466cbSJens Wiklander 952*817466cbSJens Wiklander /* 953*817466cbSJens Wiklander * Return 0 if before <= after, 1 otherwise 954*817466cbSJens Wiklander */ 955*817466cbSJens Wiklander static int x509_check_time( const mbedtls_x509_time *before, const mbedtls_x509_time *after ) 956*817466cbSJens Wiklander { 957*817466cbSJens Wiklander if( before->year > after->year ) 958*817466cbSJens Wiklander return( 1 ); 959*817466cbSJens Wiklander 960*817466cbSJens Wiklander if( before->year == after->year && 961*817466cbSJens Wiklander before->mon > after->mon ) 962*817466cbSJens Wiklander return( 1 ); 963*817466cbSJens Wiklander 964*817466cbSJens Wiklander if( before->year == after->year && 965*817466cbSJens Wiklander before->mon == after->mon && 966*817466cbSJens Wiklander before->day > after->day ) 967*817466cbSJens Wiklander return( 1 ); 968*817466cbSJens Wiklander 969*817466cbSJens Wiklander if( before->year == after->year && 970*817466cbSJens Wiklander before->mon == after->mon && 971*817466cbSJens Wiklander before->day == after->day && 972*817466cbSJens Wiklander before->hour > after->hour ) 973*817466cbSJens Wiklander return( 1 ); 974*817466cbSJens Wiklander 975*817466cbSJens Wiklander if( before->year == after->year && 976*817466cbSJens Wiklander before->mon == after->mon && 977*817466cbSJens Wiklander before->day == after->day && 978*817466cbSJens Wiklander before->hour == after->hour && 979*817466cbSJens Wiklander before->min > after->min ) 980*817466cbSJens Wiklander return( 1 ); 981*817466cbSJens Wiklander 982*817466cbSJens Wiklander if( before->year == after->year && 983*817466cbSJens Wiklander before->mon == after->mon && 984*817466cbSJens Wiklander before->day == after->day && 985*817466cbSJens Wiklander before->hour == after->hour && 986*817466cbSJens Wiklander before->min == after->min && 987*817466cbSJens Wiklander before->sec > after->sec ) 988*817466cbSJens Wiklander return( 1 ); 989*817466cbSJens Wiklander 990*817466cbSJens Wiklander return( 0 ); 991*817466cbSJens Wiklander } 992*817466cbSJens Wiklander 993*817466cbSJens Wiklander int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ) 994*817466cbSJens Wiklander { 995*817466cbSJens Wiklander mbedtls_x509_time now; 996*817466cbSJens Wiklander 997*817466cbSJens Wiklander if( x509_get_current_time( &now ) != 0 ) 998*817466cbSJens Wiklander return( 1 ); 999*817466cbSJens Wiklander 1000*817466cbSJens Wiklander return( x509_check_time( &now, to ) ); 1001*817466cbSJens Wiklander } 1002*817466cbSJens Wiklander 1003*817466cbSJens Wiklander int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ) 1004*817466cbSJens Wiklander { 1005*817466cbSJens Wiklander mbedtls_x509_time now; 1006*817466cbSJens Wiklander 1007*817466cbSJens Wiklander if( x509_get_current_time( &now ) != 0 ) 1008*817466cbSJens Wiklander return( 1 ); 1009*817466cbSJens Wiklander 1010*817466cbSJens Wiklander return( x509_check_time( from, &now ) ); 1011*817466cbSJens Wiklander } 1012*817466cbSJens Wiklander 1013*817466cbSJens Wiklander #else /* MBEDTLS_HAVE_TIME_DATE */ 1014*817466cbSJens Wiklander 1015*817466cbSJens Wiklander int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ) 1016*817466cbSJens Wiklander { 1017*817466cbSJens Wiklander ((void) to); 1018*817466cbSJens Wiklander return( 0 ); 1019*817466cbSJens Wiklander } 1020*817466cbSJens Wiklander 1021*817466cbSJens Wiklander int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ) 1022*817466cbSJens Wiklander { 1023*817466cbSJens Wiklander ((void) from); 1024*817466cbSJens Wiklander return( 0 ); 1025*817466cbSJens Wiklander } 1026*817466cbSJens Wiklander #endif /* MBEDTLS_HAVE_TIME_DATE */ 1027*817466cbSJens Wiklander 1028*817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST) 1029*817466cbSJens Wiklander 1030*817466cbSJens Wiklander #include "mbedtls/x509_crt.h" 1031*817466cbSJens Wiklander #include "mbedtls/certs.h" 1032*817466cbSJens Wiklander 1033*817466cbSJens Wiklander /* 1034*817466cbSJens Wiklander * Checkup routine 1035*817466cbSJens Wiklander */ 1036*817466cbSJens Wiklander int mbedtls_x509_self_test( int verbose ) 1037*817466cbSJens Wiklander { 1038*817466cbSJens Wiklander #if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_SHA256_C) 1039*817466cbSJens Wiklander int ret; 1040*817466cbSJens Wiklander uint32_t flags; 1041*817466cbSJens Wiklander mbedtls_x509_crt cacert; 1042*817466cbSJens Wiklander mbedtls_x509_crt clicert; 1043*817466cbSJens Wiklander 1044*817466cbSJens Wiklander if( verbose != 0 ) 1045*817466cbSJens Wiklander mbedtls_printf( " X.509 certificate load: " ); 1046*817466cbSJens Wiklander 1047*817466cbSJens Wiklander mbedtls_x509_crt_init( &clicert ); 1048*817466cbSJens Wiklander 1049*817466cbSJens Wiklander ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) mbedtls_test_cli_crt, 1050*817466cbSJens Wiklander mbedtls_test_cli_crt_len ); 1051*817466cbSJens Wiklander if( ret != 0 ) 1052*817466cbSJens Wiklander { 1053*817466cbSJens Wiklander if( verbose != 0 ) 1054*817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 1055*817466cbSJens Wiklander 1056*817466cbSJens Wiklander return( ret ); 1057*817466cbSJens Wiklander } 1058*817466cbSJens Wiklander 1059*817466cbSJens Wiklander mbedtls_x509_crt_init( &cacert ); 1060*817466cbSJens Wiklander 1061*817466cbSJens Wiklander ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_ca_crt, 1062*817466cbSJens Wiklander mbedtls_test_ca_crt_len ); 1063*817466cbSJens Wiklander if( ret != 0 ) 1064*817466cbSJens Wiklander { 1065*817466cbSJens Wiklander if( verbose != 0 ) 1066*817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 1067*817466cbSJens Wiklander 1068*817466cbSJens Wiklander return( ret ); 1069*817466cbSJens Wiklander } 1070*817466cbSJens Wiklander 1071*817466cbSJens Wiklander if( verbose != 0 ) 1072*817466cbSJens Wiklander mbedtls_printf( "passed\n X.509 signature verify: "); 1073*817466cbSJens Wiklander 1074*817466cbSJens Wiklander ret = mbedtls_x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL ); 1075*817466cbSJens Wiklander if( ret != 0 ) 1076*817466cbSJens Wiklander { 1077*817466cbSJens Wiklander if( verbose != 0 ) 1078*817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 1079*817466cbSJens Wiklander 1080*817466cbSJens Wiklander return( ret ); 1081*817466cbSJens Wiklander } 1082*817466cbSJens Wiklander 1083*817466cbSJens Wiklander if( verbose != 0 ) 1084*817466cbSJens Wiklander mbedtls_printf( "passed\n\n"); 1085*817466cbSJens Wiklander 1086*817466cbSJens Wiklander mbedtls_x509_crt_free( &cacert ); 1087*817466cbSJens Wiklander mbedtls_x509_crt_free( &clicert ); 1088*817466cbSJens Wiklander 1089*817466cbSJens Wiklander return( 0 ); 1090*817466cbSJens Wiklander #else 1091*817466cbSJens Wiklander ((void) verbose); 1092*817466cbSJens Wiklander return( 0 ); 1093*817466cbSJens Wiklander #endif /* MBEDTLS_CERTS_C && MBEDTLS_SHA1_C */ 1094*817466cbSJens Wiklander } 1095*817466cbSJens Wiklander 1096*817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST */ 1097*817466cbSJens Wiklander 1098*817466cbSJens Wiklander #endif /* MBEDTLS_X509_USE_C */ 1099