1*817466cbSJens Wiklander /* 2*817466cbSJens Wiklander * X.509 Certidicate Revocation List (CRL) parsing 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_CRL_PARSE_C) 39*817466cbSJens Wiklander 40*817466cbSJens Wiklander #include "mbedtls/x509_crl.h" 41*817466cbSJens Wiklander #include "mbedtls/oid.h" 42*817466cbSJens Wiklander 43*817466cbSJens Wiklander #include <string.h> 44*817466cbSJens Wiklander 45*817466cbSJens Wiklander #if defined(MBEDTLS_PEM_PARSE_C) 46*817466cbSJens Wiklander #include "mbedtls/pem.h" 47*817466cbSJens Wiklander #endif 48*817466cbSJens Wiklander 49*817466cbSJens Wiklander #if defined(MBEDTLS_PLATFORM_C) 50*817466cbSJens Wiklander #include "mbedtls/platform.h" 51*817466cbSJens Wiklander #else 52*817466cbSJens Wiklander #include <stdlib.h> 53*817466cbSJens Wiklander #include <stdio.h> 54*817466cbSJens Wiklander #define mbedtls_free free 55*817466cbSJens Wiklander #define mbedtls_calloc calloc 56*817466cbSJens Wiklander #define mbedtls_snprintf snprintf 57*817466cbSJens Wiklander #endif 58*817466cbSJens Wiklander 59*817466cbSJens Wiklander #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) 60*817466cbSJens Wiklander #include <windows.h> 61*817466cbSJens Wiklander #else 62*817466cbSJens Wiklander #include <time.h> 63*817466cbSJens Wiklander #endif 64*817466cbSJens Wiklander 65*817466cbSJens Wiklander #if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32) 66*817466cbSJens Wiklander #include <stdio.h> 67*817466cbSJens Wiklander #endif 68*817466cbSJens Wiklander 69*817466cbSJens Wiklander /* Implementation that should never be optimized out by the compiler */ 70*817466cbSJens Wiklander static void mbedtls_zeroize( void *v, size_t n ) { 71*817466cbSJens Wiklander volatile unsigned char *p = v; while( n-- ) *p++ = 0; 72*817466cbSJens Wiklander } 73*817466cbSJens Wiklander 74*817466cbSJens Wiklander /* 75*817466cbSJens Wiklander * Version ::= INTEGER { v1(0), v2(1) } 76*817466cbSJens Wiklander */ 77*817466cbSJens Wiklander static int x509_crl_get_version( unsigned char **p, 78*817466cbSJens Wiklander const unsigned char *end, 79*817466cbSJens Wiklander int *ver ) 80*817466cbSJens Wiklander { 81*817466cbSJens Wiklander int ret; 82*817466cbSJens Wiklander 83*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) 84*817466cbSJens Wiklander { 85*817466cbSJens Wiklander if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) 86*817466cbSJens Wiklander { 87*817466cbSJens Wiklander *ver = 0; 88*817466cbSJens Wiklander return( 0 ); 89*817466cbSJens Wiklander } 90*817466cbSJens Wiklander 91*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_VERSION + ret ); 92*817466cbSJens Wiklander } 93*817466cbSJens Wiklander 94*817466cbSJens Wiklander return( 0 ); 95*817466cbSJens Wiklander } 96*817466cbSJens Wiklander 97*817466cbSJens Wiklander /* 98*817466cbSJens Wiklander * X.509 CRL v2 extensions (no extensions parsed yet.) 99*817466cbSJens Wiklander */ 100*817466cbSJens Wiklander static int x509_get_crl_ext( unsigned char **p, 101*817466cbSJens Wiklander const unsigned char *end, 102*817466cbSJens Wiklander mbedtls_x509_buf *ext ) 103*817466cbSJens Wiklander { 104*817466cbSJens Wiklander int ret; 105*817466cbSJens Wiklander size_t len = 0; 106*817466cbSJens Wiklander 107*817466cbSJens Wiklander /* Get explicit tag */ 108*817466cbSJens Wiklander if( ( ret = mbedtls_x509_get_ext( p, end, ext, 0) ) != 0 ) 109*817466cbSJens Wiklander { 110*817466cbSJens Wiklander if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) 111*817466cbSJens Wiklander return( 0 ); 112*817466cbSJens Wiklander 113*817466cbSJens Wiklander return( ret ); 114*817466cbSJens Wiklander } 115*817466cbSJens Wiklander 116*817466cbSJens Wiklander while( *p < end ) 117*817466cbSJens Wiklander { 118*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( p, end, &len, 119*817466cbSJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) 120*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); 121*817466cbSJens Wiklander 122*817466cbSJens Wiklander *p += len; 123*817466cbSJens Wiklander } 124*817466cbSJens Wiklander 125*817466cbSJens Wiklander if( *p != end ) 126*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + 127*817466cbSJens Wiklander MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); 128*817466cbSJens Wiklander 129*817466cbSJens Wiklander return( 0 ); 130*817466cbSJens Wiklander } 131*817466cbSJens Wiklander 132*817466cbSJens Wiklander /* 133*817466cbSJens Wiklander * X.509 CRL v2 entry extensions (no extensions parsed yet.) 134*817466cbSJens Wiklander */ 135*817466cbSJens Wiklander static int x509_get_crl_entry_ext( unsigned char **p, 136*817466cbSJens Wiklander const unsigned char *end, 137*817466cbSJens Wiklander mbedtls_x509_buf *ext ) 138*817466cbSJens Wiklander { 139*817466cbSJens Wiklander int ret; 140*817466cbSJens Wiklander size_t len = 0; 141*817466cbSJens Wiklander 142*817466cbSJens Wiklander /* OPTIONAL */ 143*817466cbSJens Wiklander if( end <= *p ) 144*817466cbSJens Wiklander return( 0 ); 145*817466cbSJens Wiklander 146*817466cbSJens Wiklander ext->tag = **p; 147*817466cbSJens Wiklander ext->p = *p; 148*817466cbSJens Wiklander 149*817466cbSJens Wiklander /* 150*817466cbSJens Wiklander * Get CRL-entry extension sequence header 151*817466cbSJens Wiklander * crlEntryExtensions Extensions OPTIONAL -- if present, MUST be v2 152*817466cbSJens Wiklander */ 153*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( p, end, &ext->len, 154*817466cbSJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) 155*817466cbSJens Wiklander { 156*817466cbSJens Wiklander if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) 157*817466cbSJens Wiklander { 158*817466cbSJens Wiklander ext->p = NULL; 159*817466cbSJens Wiklander return( 0 ); 160*817466cbSJens Wiklander } 161*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); 162*817466cbSJens Wiklander } 163*817466cbSJens Wiklander 164*817466cbSJens Wiklander end = *p + ext->len; 165*817466cbSJens Wiklander 166*817466cbSJens Wiklander if( end != *p + ext->len ) 167*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + 168*817466cbSJens Wiklander MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); 169*817466cbSJens Wiklander 170*817466cbSJens Wiklander while( *p < end ) 171*817466cbSJens Wiklander { 172*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( p, end, &len, 173*817466cbSJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) 174*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); 175*817466cbSJens Wiklander 176*817466cbSJens Wiklander *p += len; 177*817466cbSJens Wiklander } 178*817466cbSJens Wiklander 179*817466cbSJens Wiklander if( *p != end ) 180*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + 181*817466cbSJens Wiklander MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); 182*817466cbSJens Wiklander 183*817466cbSJens Wiklander return( 0 ); 184*817466cbSJens Wiklander } 185*817466cbSJens Wiklander 186*817466cbSJens Wiklander /* 187*817466cbSJens Wiklander * X.509 CRL Entries 188*817466cbSJens Wiklander */ 189*817466cbSJens Wiklander static int x509_get_entries( unsigned char **p, 190*817466cbSJens Wiklander const unsigned char *end, 191*817466cbSJens Wiklander mbedtls_x509_crl_entry *entry ) 192*817466cbSJens Wiklander { 193*817466cbSJens Wiklander int ret; 194*817466cbSJens Wiklander size_t entry_len; 195*817466cbSJens Wiklander mbedtls_x509_crl_entry *cur_entry = entry; 196*817466cbSJens Wiklander 197*817466cbSJens Wiklander if( *p == end ) 198*817466cbSJens Wiklander return( 0 ); 199*817466cbSJens Wiklander 200*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( p, end, &entry_len, 201*817466cbSJens Wiklander MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED ) ) != 0 ) 202*817466cbSJens Wiklander { 203*817466cbSJens Wiklander if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) 204*817466cbSJens Wiklander return( 0 ); 205*817466cbSJens Wiklander 206*817466cbSJens Wiklander return( ret ); 207*817466cbSJens Wiklander } 208*817466cbSJens Wiklander 209*817466cbSJens Wiklander end = *p + entry_len; 210*817466cbSJens Wiklander 211*817466cbSJens Wiklander while( *p < end ) 212*817466cbSJens Wiklander { 213*817466cbSJens Wiklander size_t len2; 214*817466cbSJens Wiklander const unsigned char *end2; 215*817466cbSJens Wiklander 216*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( p, end, &len2, 217*817466cbSJens Wiklander MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED ) ) != 0 ) 218*817466cbSJens Wiklander { 219*817466cbSJens Wiklander return( ret ); 220*817466cbSJens Wiklander } 221*817466cbSJens Wiklander 222*817466cbSJens Wiklander cur_entry->raw.tag = **p; 223*817466cbSJens Wiklander cur_entry->raw.p = *p; 224*817466cbSJens Wiklander cur_entry->raw.len = len2; 225*817466cbSJens Wiklander end2 = *p + len2; 226*817466cbSJens Wiklander 227*817466cbSJens Wiklander if( ( ret = mbedtls_x509_get_serial( p, end2, &cur_entry->serial ) ) != 0 ) 228*817466cbSJens Wiklander return( ret ); 229*817466cbSJens Wiklander 230*817466cbSJens Wiklander if( ( ret = mbedtls_x509_get_time( p, end2, 231*817466cbSJens Wiklander &cur_entry->revocation_date ) ) != 0 ) 232*817466cbSJens Wiklander return( ret ); 233*817466cbSJens Wiklander 234*817466cbSJens Wiklander if( ( ret = x509_get_crl_entry_ext( p, end2, 235*817466cbSJens Wiklander &cur_entry->entry_ext ) ) != 0 ) 236*817466cbSJens Wiklander return( ret ); 237*817466cbSJens Wiklander 238*817466cbSJens Wiklander if( *p < end ) 239*817466cbSJens Wiklander { 240*817466cbSJens Wiklander cur_entry->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl_entry ) ); 241*817466cbSJens Wiklander 242*817466cbSJens Wiklander if( cur_entry->next == NULL ) 243*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_ALLOC_FAILED ); 244*817466cbSJens Wiklander 245*817466cbSJens Wiklander cur_entry = cur_entry->next; 246*817466cbSJens Wiklander } 247*817466cbSJens Wiklander } 248*817466cbSJens Wiklander 249*817466cbSJens Wiklander return( 0 ); 250*817466cbSJens Wiklander } 251*817466cbSJens Wiklander 252*817466cbSJens Wiklander /* 253*817466cbSJens Wiklander * Parse one CRLs in DER format and append it to the chained list 254*817466cbSJens Wiklander */ 255*817466cbSJens Wiklander int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, 256*817466cbSJens Wiklander const unsigned char *buf, size_t buflen ) 257*817466cbSJens Wiklander { 258*817466cbSJens Wiklander int ret; 259*817466cbSJens Wiklander size_t len; 260*817466cbSJens Wiklander unsigned char *p, *end; 261*817466cbSJens Wiklander mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; 262*817466cbSJens Wiklander mbedtls_x509_crl *crl = chain; 263*817466cbSJens Wiklander 264*817466cbSJens Wiklander /* 265*817466cbSJens Wiklander * Check for valid input 266*817466cbSJens Wiklander */ 267*817466cbSJens Wiklander if( crl == NULL || buf == NULL ) 268*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); 269*817466cbSJens Wiklander 270*817466cbSJens Wiklander memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) ); 271*817466cbSJens Wiklander memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) ); 272*817466cbSJens Wiklander memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) ); 273*817466cbSJens Wiklander 274*817466cbSJens Wiklander /* 275*817466cbSJens Wiklander * Add new CRL on the end of the chain if needed. 276*817466cbSJens Wiklander */ 277*817466cbSJens Wiklander while( crl->version != 0 && crl->next != NULL ) 278*817466cbSJens Wiklander crl = crl->next; 279*817466cbSJens Wiklander 280*817466cbSJens Wiklander if( crl->version != 0 && crl->next == NULL ) 281*817466cbSJens Wiklander { 282*817466cbSJens Wiklander crl->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl ) ); 283*817466cbSJens Wiklander 284*817466cbSJens Wiklander if( crl->next == NULL ) 285*817466cbSJens Wiklander { 286*817466cbSJens Wiklander mbedtls_x509_crl_free( crl ); 287*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_ALLOC_FAILED ); 288*817466cbSJens Wiklander } 289*817466cbSJens Wiklander 290*817466cbSJens Wiklander mbedtls_x509_crl_init( crl->next ); 291*817466cbSJens Wiklander crl = crl->next; 292*817466cbSJens Wiklander } 293*817466cbSJens Wiklander 294*817466cbSJens Wiklander /* 295*817466cbSJens Wiklander * Copy raw DER-encoded CRL 296*817466cbSJens Wiklander */ 297*817466cbSJens Wiklander if( ( p = mbedtls_calloc( 1, buflen ) ) == NULL ) 298*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_ALLOC_FAILED ); 299*817466cbSJens Wiklander 300*817466cbSJens Wiklander memcpy( p, buf, buflen ); 301*817466cbSJens Wiklander 302*817466cbSJens Wiklander crl->raw.p = p; 303*817466cbSJens Wiklander crl->raw.len = buflen; 304*817466cbSJens Wiklander 305*817466cbSJens Wiklander end = p + buflen; 306*817466cbSJens Wiklander 307*817466cbSJens Wiklander /* 308*817466cbSJens Wiklander * CertificateList ::= SEQUENCE { 309*817466cbSJens Wiklander * tbsCertList TBSCertList, 310*817466cbSJens Wiklander * signatureAlgorithm AlgorithmIdentifier, 311*817466cbSJens Wiklander * signatureValue BIT STRING } 312*817466cbSJens Wiklander */ 313*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, 314*817466cbSJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) 315*817466cbSJens Wiklander { 316*817466cbSJens Wiklander mbedtls_x509_crl_free( crl ); 317*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_FORMAT ); 318*817466cbSJens Wiklander } 319*817466cbSJens Wiklander 320*817466cbSJens Wiklander if( len != (size_t) ( end - p ) ) 321*817466cbSJens Wiklander { 322*817466cbSJens Wiklander mbedtls_x509_crl_free( crl ); 323*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_FORMAT + 324*817466cbSJens Wiklander MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); 325*817466cbSJens Wiklander } 326*817466cbSJens Wiklander 327*817466cbSJens Wiklander /* 328*817466cbSJens Wiklander * TBSCertList ::= SEQUENCE { 329*817466cbSJens Wiklander */ 330*817466cbSJens Wiklander crl->tbs.p = p; 331*817466cbSJens Wiklander 332*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, 333*817466cbSJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) 334*817466cbSJens Wiklander { 335*817466cbSJens Wiklander mbedtls_x509_crl_free( crl ); 336*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); 337*817466cbSJens Wiklander } 338*817466cbSJens Wiklander 339*817466cbSJens Wiklander end = p + len; 340*817466cbSJens Wiklander crl->tbs.len = end - crl->tbs.p; 341*817466cbSJens Wiklander 342*817466cbSJens Wiklander /* 343*817466cbSJens Wiklander * Version ::= INTEGER OPTIONAL { v1(0), v2(1) } 344*817466cbSJens Wiklander * -- if present, MUST be v2 345*817466cbSJens Wiklander * 346*817466cbSJens Wiklander * signature AlgorithmIdentifier 347*817466cbSJens Wiklander */ 348*817466cbSJens Wiklander if( ( ret = x509_crl_get_version( &p, end, &crl->version ) ) != 0 || 349*817466cbSJens Wiklander ( ret = mbedtls_x509_get_alg( &p, end, &crl->sig_oid, &sig_params1 ) ) != 0 ) 350*817466cbSJens Wiklander { 351*817466cbSJens Wiklander mbedtls_x509_crl_free( crl ); 352*817466cbSJens Wiklander return( ret ); 353*817466cbSJens Wiklander } 354*817466cbSJens Wiklander 355*817466cbSJens Wiklander if( crl->version < 0 || crl->version > 1 ) 356*817466cbSJens Wiklander { 357*817466cbSJens Wiklander mbedtls_x509_crl_free( crl ); 358*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); 359*817466cbSJens Wiklander } 360*817466cbSJens Wiklander 361*817466cbSJens Wiklander crl->version++; 362*817466cbSJens Wiklander 363*817466cbSJens Wiklander if( ( ret = mbedtls_x509_get_sig_alg( &crl->sig_oid, &sig_params1, 364*817466cbSJens Wiklander &crl->sig_md, &crl->sig_pk, 365*817466cbSJens Wiklander &crl->sig_opts ) ) != 0 ) 366*817466cbSJens Wiklander { 367*817466cbSJens Wiklander mbedtls_x509_crl_free( crl ); 368*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG ); 369*817466cbSJens Wiklander } 370*817466cbSJens Wiklander 371*817466cbSJens Wiklander /* 372*817466cbSJens Wiklander * issuer Name 373*817466cbSJens Wiklander */ 374*817466cbSJens Wiklander crl->issuer_raw.p = p; 375*817466cbSJens Wiklander 376*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, 377*817466cbSJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) 378*817466cbSJens Wiklander { 379*817466cbSJens Wiklander mbedtls_x509_crl_free( crl ); 380*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); 381*817466cbSJens Wiklander } 382*817466cbSJens Wiklander 383*817466cbSJens Wiklander if( ( ret = mbedtls_x509_get_name( &p, p + len, &crl->issuer ) ) != 0 ) 384*817466cbSJens Wiklander { 385*817466cbSJens Wiklander mbedtls_x509_crl_free( crl ); 386*817466cbSJens Wiklander return( ret ); 387*817466cbSJens Wiklander } 388*817466cbSJens Wiklander 389*817466cbSJens Wiklander crl->issuer_raw.len = p - crl->issuer_raw.p; 390*817466cbSJens Wiklander 391*817466cbSJens Wiklander /* 392*817466cbSJens Wiklander * thisUpdate Time 393*817466cbSJens Wiklander * nextUpdate Time OPTIONAL 394*817466cbSJens Wiklander */ 395*817466cbSJens Wiklander if( ( ret = mbedtls_x509_get_time( &p, end, &crl->this_update ) ) != 0 ) 396*817466cbSJens Wiklander { 397*817466cbSJens Wiklander mbedtls_x509_crl_free( crl ); 398*817466cbSJens Wiklander return( ret ); 399*817466cbSJens Wiklander } 400*817466cbSJens Wiklander 401*817466cbSJens Wiklander if( ( ret = mbedtls_x509_get_time( &p, end, &crl->next_update ) ) != 0 ) 402*817466cbSJens Wiklander { 403*817466cbSJens Wiklander if( ret != ( MBEDTLS_ERR_X509_INVALID_DATE + 404*817466cbSJens Wiklander MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) && 405*817466cbSJens Wiklander ret != ( MBEDTLS_ERR_X509_INVALID_DATE + 406*817466cbSJens Wiklander MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ) 407*817466cbSJens Wiklander { 408*817466cbSJens Wiklander mbedtls_x509_crl_free( crl ); 409*817466cbSJens Wiklander return( ret ); 410*817466cbSJens Wiklander } 411*817466cbSJens Wiklander } 412*817466cbSJens Wiklander 413*817466cbSJens Wiklander /* 414*817466cbSJens Wiklander * revokedCertificates SEQUENCE OF SEQUENCE { 415*817466cbSJens Wiklander * userCertificate CertificateSerialNumber, 416*817466cbSJens Wiklander * revocationDate Time, 417*817466cbSJens Wiklander * crlEntryExtensions Extensions OPTIONAL 418*817466cbSJens Wiklander * -- if present, MUST be v2 419*817466cbSJens Wiklander * } OPTIONAL 420*817466cbSJens Wiklander */ 421*817466cbSJens Wiklander if( ( ret = x509_get_entries( &p, end, &crl->entry ) ) != 0 ) 422*817466cbSJens Wiklander { 423*817466cbSJens Wiklander mbedtls_x509_crl_free( crl ); 424*817466cbSJens Wiklander return( ret ); 425*817466cbSJens Wiklander } 426*817466cbSJens Wiklander 427*817466cbSJens Wiklander /* 428*817466cbSJens Wiklander * crlExtensions EXPLICIT Extensions OPTIONAL 429*817466cbSJens Wiklander * -- if present, MUST be v2 430*817466cbSJens Wiklander */ 431*817466cbSJens Wiklander if( crl->version == 2 ) 432*817466cbSJens Wiklander { 433*817466cbSJens Wiklander ret = x509_get_crl_ext( &p, end, &crl->crl_ext ); 434*817466cbSJens Wiklander 435*817466cbSJens Wiklander if( ret != 0 ) 436*817466cbSJens Wiklander { 437*817466cbSJens Wiklander mbedtls_x509_crl_free( crl ); 438*817466cbSJens Wiklander return( ret ); 439*817466cbSJens Wiklander } 440*817466cbSJens Wiklander } 441*817466cbSJens Wiklander 442*817466cbSJens Wiklander if( p != end ) 443*817466cbSJens Wiklander { 444*817466cbSJens Wiklander mbedtls_x509_crl_free( crl ); 445*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_FORMAT + 446*817466cbSJens Wiklander MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); 447*817466cbSJens Wiklander } 448*817466cbSJens Wiklander 449*817466cbSJens Wiklander end = crl->raw.p + crl->raw.len; 450*817466cbSJens Wiklander 451*817466cbSJens Wiklander /* 452*817466cbSJens Wiklander * signatureAlgorithm AlgorithmIdentifier, 453*817466cbSJens Wiklander * signatureValue BIT STRING 454*817466cbSJens Wiklander */ 455*817466cbSJens Wiklander if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 ) 456*817466cbSJens Wiklander { 457*817466cbSJens Wiklander mbedtls_x509_crl_free( crl ); 458*817466cbSJens Wiklander return( ret ); 459*817466cbSJens Wiklander } 460*817466cbSJens Wiklander 461*817466cbSJens Wiklander if( crl->sig_oid.len != sig_oid2.len || 462*817466cbSJens Wiklander memcmp( crl->sig_oid.p, sig_oid2.p, crl->sig_oid.len ) != 0 || 463*817466cbSJens Wiklander sig_params1.len != sig_params2.len || 464*817466cbSJens Wiklander ( sig_params1.len != 0 && 465*817466cbSJens Wiklander memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) ) 466*817466cbSJens Wiklander { 467*817466cbSJens Wiklander mbedtls_x509_crl_free( crl ); 468*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_SIG_MISMATCH ); 469*817466cbSJens Wiklander } 470*817466cbSJens Wiklander 471*817466cbSJens Wiklander if( ( ret = mbedtls_x509_get_sig( &p, end, &crl->sig ) ) != 0 ) 472*817466cbSJens Wiklander { 473*817466cbSJens Wiklander mbedtls_x509_crl_free( crl ); 474*817466cbSJens Wiklander return( ret ); 475*817466cbSJens Wiklander } 476*817466cbSJens Wiklander 477*817466cbSJens Wiklander if( p != end ) 478*817466cbSJens Wiklander { 479*817466cbSJens Wiklander mbedtls_x509_crl_free( crl ); 480*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_INVALID_FORMAT + 481*817466cbSJens Wiklander MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); 482*817466cbSJens Wiklander } 483*817466cbSJens Wiklander 484*817466cbSJens Wiklander return( 0 ); 485*817466cbSJens Wiklander } 486*817466cbSJens Wiklander 487*817466cbSJens Wiklander /* 488*817466cbSJens Wiklander * Parse one or more CRLs and add them to the chained list 489*817466cbSJens Wiklander */ 490*817466cbSJens Wiklander int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen ) 491*817466cbSJens Wiklander { 492*817466cbSJens Wiklander #if defined(MBEDTLS_PEM_PARSE_C) 493*817466cbSJens Wiklander int ret; 494*817466cbSJens Wiklander size_t use_len; 495*817466cbSJens Wiklander mbedtls_pem_context pem; 496*817466cbSJens Wiklander int is_pem = 0; 497*817466cbSJens Wiklander 498*817466cbSJens Wiklander if( chain == NULL || buf == NULL ) 499*817466cbSJens Wiklander return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); 500*817466cbSJens Wiklander 501*817466cbSJens Wiklander do 502*817466cbSJens Wiklander { 503*817466cbSJens Wiklander mbedtls_pem_init( &pem ); 504*817466cbSJens Wiklander 505*817466cbSJens Wiklander // Avoid calling mbedtls_pem_read_buffer() on non-null-terminated 506*817466cbSJens Wiklander // string 507*817466cbSJens Wiklander if( buflen == 0 || buf[buflen - 1] != '\0' ) 508*817466cbSJens Wiklander ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; 509*817466cbSJens Wiklander else 510*817466cbSJens Wiklander ret = mbedtls_pem_read_buffer( &pem, 511*817466cbSJens Wiklander "-----BEGIN X509 CRL-----", 512*817466cbSJens Wiklander "-----END X509 CRL-----", 513*817466cbSJens Wiklander buf, NULL, 0, &use_len ); 514*817466cbSJens Wiklander 515*817466cbSJens Wiklander if( ret == 0 ) 516*817466cbSJens Wiklander { 517*817466cbSJens Wiklander /* 518*817466cbSJens Wiklander * Was PEM encoded 519*817466cbSJens Wiklander */ 520*817466cbSJens Wiklander is_pem = 1; 521*817466cbSJens Wiklander 522*817466cbSJens Wiklander buflen -= use_len; 523*817466cbSJens Wiklander buf += use_len; 524*817466cbSJens Wiklander 525*817466cbSJens Wiklander if( ( ret = mbedtls_x509_crl_parse_der( chain, 526*817466cbSJens Wiklander pem.buf, pem.buflen ) ) != 0 ) 527*817466cbSJens Wiklander { 528*817466cbSJens Wiklander mbedtls_pem_free( &pem ); 529*817466cbSJens Wiklander return( ret ); 530*817466cbSJens Wiklander } 531*817466cbSJens Wiklander } 532*817466cbSJens Wiklander else if( is_pem ) 533*817466cbSJens Wiklander { 534*817466cbSJens Wiklander mbedtls_pem_free( &pem ); 535*817466cbSJens Wiklander return( ret ); 536*817466cbSJens Wiklander } 537*817466cbSJens Wiklander 538*817466cbSJens Wiklander mbedtls_pem_free( &pem ); 539*817466cbSJens Wiklander } 540*817466cbSJens Wiklander /* In the PEM case, buflen is 1 at the end, for the terminated NULL byte. 541*817466cbSJens Wiklander * And a valid CRL cannot be less than 1 byte anyway. */ 542*817466cbSJens Wiklander while( is_pem && buflen > 1 ); 543*817466cbSJens Wiklander 544*817466cbSJens Wiklander if( is_pem ) 545*817466cbSJens Wiklander return( 0 ); 546*817466cbSJens Wiklander else 547*817466cbSJens Wiklander #endif /* MBEDTLS_PEM_PARSE_C */ 548*817466cbSJens Wiklander return( mbedtls_x509_crl_parse_der( chain, buf, buflen ) ); 549*817466cbSJens Wiklander } 550*817466cbSJens Wiklander 551*817466cbSJens Wiklander #if defined(MBEDTLS_FS_IO) 552*817466cbSJens Wiklander /* 553*817466cbSJens Wiklander * Load one or more CRLs and add them to the chained list 554*817466cbSJens Wiklander */ 555*817466cbSJens Wiklander int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path ) 556*817466cbSJens Wiklander { 557*817466cbSJens Wiklander int ret; 558*817466cbSJens Wiklander size_t n; 559*817466cbSJens Wiklander unsigned char *buf; 560*817466cbSJens Wiklander 561*817466cbSJens Wiklander if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) 562*817466cbSJens Wiklander return( ret ); 563*817466cbSJens Wiklander 564*817466cbSJens Wiklander ret = mbedtls_x509_crl_parse( chain, buf, n ); 565*817466cbSJens Wiklander 566*817466cbSJens Wiklander mbedtls_zeroize( buf, n ); 567*817466cbSJens Wiklander mbedtls_free( buf ); 568*817466cbSJens Wiklander 569*817466cbSJens Wiklander return( ret ); 570*817466cbSJens Wiklander } 571*817466cbSJens Wiklander #endif /* MBEDTLS_FS_IO */ 572*817466cbSJens Wiklander 573*817466cbSJens Wiklander /* 574*817466cbSJens Wiklander * Return an informational string about the certificate. 575*817466cbSJens Wiklander */ 576*817466cbSJens Wiklander #define BEFORE_COLON 14 577*817466cbSJens Wiklander #define BC "14" 578*817466cbSJens Wiklander /* 579*817466cbSJens Wiklander * Return an informational string about the CRL. 580*817466cbSJens Wiklander */ 581*817466cbSJens Wiklander int mbedtls_x509_crl_info( char *buf, size_t size, const char *prefix, 582*817466cbSJens Wiklander const mbedtls_x509_crl *crl ) 583*817466cbSJens Wiklander { 584*817466cbSJens Wiklander int ret; 585*817466cbSJens Wiklander size_t n; 586*817466cbSJens Wiklander char *p; 587*817466cbSJens Wiklander const mbedtls_x509_crl_entry *entry; 588*817466cbSJens Wiklander 589*817466cbSJens Wiklander p = buf; 590*817466cbSJens Wiklander n = size; 591*817466cbSJens Wiklander 592*817466cbSJens Wiklander ret = mbedtls_snprintf( p, n, "%sCRL version : %d", 593*817466cbSJens Wiklander prefix, crl->version ); 594*817466cbSJens Wiklander MBEDTLS_X509_SAFE_SNPRINTF; 595*817466cbSJens Wiklander 596*817466cbSJens Wiklander ret = mbedtls_snprintf( p, n, "\n%sissuer name : ", prefix ); 597*817466cbSJens Wiklander MBEDTLS_X509_SAFE_SNPRINTF; 598*817466cbSJens Wiklander ret = mbedtls_x509_dn_gets( p, n, &crl->issuer ); 599*817466cbSJens Wiklander MBEDTLS_X509_SAFE_SNPRINTF; 600*817466cbSJens Wiklander 601*817466cbSJens Wiklander ret = mbedtls_snprintf( p, n, "\n%sthis update : " \ 602*817466cbSJens Wiklander "%04d-%02d-%02d %02d:%02d:%02d", prefix, 603*817466cbSJens Wiklander crl->this_update.year, crl->this_update.mon, 604*817466cbSJens Wiklander crl->this_update.day, crl->this_update.hour, 605*817466cbSJens Wiklander crl->this_update.min, crl->this_update.sec ); 606*817466cbSJens Wiklander MBEDTLS_X509_SAFE_SNPRINTF; 607*817466cbSJens Wiklander 608*817466cbSJens Wiklander ret = mbedtls_snprintf( p, n, "\n%snext update : " \ 609*817466cbSJens Wiklander "%04d-%02d-%02d %02d:%02d:%02d", prefix, 610*817466cbSJens Wiklander crl->next_update.year, crl->next_update.mon, 611*817466cbSJens Wiklander crl->next_update.day, crl->next_update.hour, 612*817466cbSJens Wiklander crl->next_update.min, crl->next_update.sec ); 613*817466cbSJens Wiklander MBEDTLS_X509_SAFE_SNPRINTF; 614*817466cbSJens Wiklander 615*817466cbSJens Wiklander entry = &crl->entry; 616*817466cbSJens Wiklander 617*817466cbSJens Wiklander ret = mbedtls_snprintf( p, n, "\n%sRevoked certificates:", 618*817466cbSJens Wiklander prefix ); 619*817466cbSJens Wiklander MBEDTLS_X509_SAFE_SNPRINTF; 620*817466cbSJens Wiklander 621*817466cbSJens Wiklander while( entry != NULL && entry->raw.len != 0 ) 622*817466cbSJens Wiklander { 623*817466cbSJens Wiklander ret = mbedtls_snprintf( p, n, "\n%sserial number: ", 624*817466cbSJens Wiklander prefix ); 625*817466cbSJens Wiklander MBEDTLS_X509_SAFE_SNPRINTF; 626*817466cbSJens Wiklander 627*817466cbSJens Wiklander ret = mbedtls_x509_serial_gets( p, n, &entry->serial ); 628*817466cbSJens Wiklander MBEDTLS_X509_SAFE_SNPRINTF; 629*817466cbSJens Wiklander 630*817466cbSJens Wiklander ret = mbedtls_snprintf( p, n, " revocation date: " \ 631*817466cbSJens Wiklander "%04d-%02d-%02d %02d:%02d:%02d", 632*817466cbSJens Wiklander entry->revocation_date.year, entry->revocation_date.mon, 633*817466cbSJens Wiklander entry->revocation_date.day, entry->revocation_date.hour, 634*817466cbSJens Wiklander entry->revocation_date.min, entry->revocation_date.sec ); 635*817466cbSJens Wiklander MBEDTLS_X509_SAFE_SNPRINTF; 636*817466cbSJens Wiklander 637*817466cbSJens Wiklander entry = entry->next; 638*817466cbSJens Wiklander } 639*817466cbSJens Wiklander 640*817466cbSJens Wiklander ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); 641*817466cbSJens Wiklander MBEDTLS_X509_SAFE_SNPRINTF; 642*817466cbSJens Wiklander 643*817466cbSJens Wiklander ret = mbedtls_x509_sig_alg_gets( p, n, &crl->sig_oid, crl->sig_pk, crl->sig_md, 644*817466cbSJens Wiklander crl->sig_opts ); 645*817466cbSJens Wiklander MBEDTLS_X509_SAFE_SNPRINTF; 646*817466cbSJens Wiklander 647*817466cbSJens Wiklander ret = mbedtls_snprintf( p, n, "\n" ); 648*817466cbSJens Wiklander MBEDTLS_X509_SAFE_SNPRINTF; 649*817466cbSJens Wiklander 650*817466cbSJens Wiklander return( (int) ( size - n ) ); 651*817466cbSJens Wiklander } 652*817466cbSJens Wiklander 653*817466cbSJens Wiklander /* 654*817466cbSJens Wiklander * Initialize a CRL chain 655*817466cbSJens Wiklander */ 656*817466cbSJens Wiklander void mbedtls_x509_crl_init( mbedtls_x509_crl *crl ) 657*817466cbSJens Wiklander { 658*817466cbSJens Wiklander memset( crl, 0, sizeof(mbedtls_x509_crl) ); 659*817466cbSJens Wiklander } 660*817466cbSJens Wiklander 661*817466cbSJens Wiklander /* 662*817466cbSJens Wiklander * Unallocate all CRL data 663*817466cbSJens Wiklander */ 664*817466cbSJens Wiklander void mbedtls_x509_crl_free( mbedtls_x509_crl *crl ) 665*817466cbSJens Wiklander { 666*817466cbSJens Wiklander mbedtls_x509_crl *crl_cur = crl; 667*817466cbSJens Wiklander mbedtls_x509_crl *crl_prv; 668*817466cbSJens Wiklander mbedtls_x509_name *name_cur; 669*817466cbSJens Wiklander mbedtls_x509_name *name_prv; 670*817466cbSJens Wiklander mbedtls_x509_crl_entry *entry_cur; 671*817466cbSJens Wiklander mbedtls_x509_crl_entry *entry_prv; 672*817466cbSJens Wiklander 673*817466cbSJens Wiklander if( crl == NULL ) 674*817466cbSJens Wiklander return; 675*817466cbSJens Wiklander 676*817466cbSJens Wiklander do 677*817466cbSJens Wiklander { 678*817466cbSJens Wiklander #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) 679*817466cbSJens Wiklander mbedtls_free( crl_cur->sig_opts ); 680*817466cbSJens Wiklander #endif 681*817466cbSJens Wiklander 682*817466cbSJens Wiklander name_cur = crl_cur->issuer.next; 683*817466cbSJens Wiklander while( name_cur != NULL ) 684*817466cbSJens Wiklander { 685*817466cbSJens Wiklander name_prv = name_cur; 686*817466cbSJens Wiklander name_cur = name_cur->next; 687*817466cbSJens Wiklander mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); 688*817466cbSJens Wiklander mbedtls_free( name_prv ); 689*817466cbSJens Wiklander } 690*817466cbSJens Wiklander 691*817466cbSJens Wiklander entry_cur = crl_cur->entry.next; 692*817466cbSJens Wiklander while( entry_cur != NULL ) 693*817466cbSJens Wiklander { 694*817466cbSJens Wiklander entry_prv = entry_cur; 695*817466cbSJens Wiklander entry_cur = entry_cur->next; 696*817466cbSJens Wiklander mbedtls_zeroize( entry_prv, sizeof( mbedtls_x509_crl_entry ) ); 697*817466cbSJens Wiklander mbedtls_free( entry_prv ); 698*817466cbSJens Wiklander } 699*817466cbSJens Wiklander 700*817466cbSJens Wiklander if( crl_cur->raw.p != NULL ) 701*817466cbSJens Wiklander { 702*817466cbSJens Wiklander mbedtls_zeroize( crl_cur->raw.p, crl_cur->raw.len ); 703*817466cbSJens Wiklander mbedtls_free( crl_cur->raw.p ); 704*817466cbSJens Wiklander } 705*817466cbSJens Wiklander 706*817466cbSJens Wiklander crl_cur = crl_cur->next; 707*817466cbSJens Wiklander } 708*817466cbSJens Wiklander while( crl_cur != NULL ); 709*817466cbSJens Wiklander 710*817466cbSJens Wiklander crl_cur = crl; 711*817466cbSJens Wiklander do 712*817466cbSJens Wiklander { 713*817466cbSJens Wiklander crl_prv = crl_cur; 714*817466cbSJens Wiklander crl_cur = crl_cur->next; 715*817466cbSJens Wiklander 716*817466cbSJens Wiklander mbedtls_zeroize( crl_prv, sizeof( mbedtls_x509_crl ) ); 717*817466cbSJens Wiklander if( crl_prv != crl ) 718*817466cbSJens Wiklander mbedtls_free( crl_prv ); 719*817466cbSJens Wiklander } 720*817466cbSJens Wiklander while( crl_cur != NULL ); 721*817466cbSJens Wiklander } 722*817466cbSJens Wiklander 723*817466cbSJens Wiklander #endif /* MBEDTLS_X509_CRL_PARSE_C */ 724