takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Committer:
kadonotakashi
Date:
Thu Oct 11 02:27:46 2018 +0000
Revision:
3:f3764f852aa8
Parent:
0:8fdf9a60065b
Nucreo 446 + SSD1331 test version;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kadonotakashi 0:8fdf9a60065b 1 /*
kadonotakashi 0:8fdf9a60065b 2 * X.509 certificate parsing and verification
kadonotakashi 0:8fdf9a60065b 3 *
kadonotakashi 0:8fdf9a60065b 4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
kadonotakashi 0:8fdf9a60065b 5 * SPDX-License-Identifier: Apache-2.0
kadonotakashi 0:8fdf9a60065b 6 *
kadonotakashi 0:8fdf9a60065b 7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
kadonotakashi 0:8fdf9a60065b 8 * not use this file except in compliance with the License.
kadonotakashi 0:8fdf9a60065b 9 * You may obtain a copy of the License at
kadonotakashi 0:8fdf9a60065b 10 *
kadonotakashi 0:8fdf9a60065b 11 * http://www.apache.org/licenses/LICENSE-2.0
kadonotakashi 0:8fdf9a60065b 12 *
kadonotakashi 0:8fdf9a60065b 13 * Unless required by applicable law or agreed to in writing, software
kadonotakashi 0:8fdf9a60065b 14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
kadonotakashi 0:8fdf9a60065b 15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kadonotakashi 0:8fdf9a60065b 16 * See the License for the specific language governing permissions and
kadonotakashi 0:8fdf9a60065b 17 * limitations under the License.
kadonotakashi 0:8fdf9a60065b 18 *
kadonotakashi 0:8fdf9a60065b 19 * This file is part of mbed TLS (https://tls.mbed.org)
kadonotakashi 0:8fdf9a60065b 20 */
kadonotakashi 0:8fdf9a60065b 21 /*
kadonotakashi 0:8fdf9a60065b 22 * The ITU-T X.509 standard defines a certificate format for PKI.
kadonotakashi 0:8fdf9a60065b 23 *
kadonotakashi 0:8fdf9a60065b 24 * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)
kadonotakashi 0:8fdf9a60065b 25 * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
kadonotakashi 0:8fdf9a60065b 26 * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
kadonotakashi 0:8fdf9a60065b 27 *
kadonotakashi 0:8fdf9a60065b 28 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
kadonotakashi 0:8fdf9a60065b 29 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
kadonotakashi 0:8fdf9a60065b 30 *
kadonotakashi 0:8fdf9a60065b 31 * [SIRO] https://cabforum.org/wp-content/uploads/Chunghwatelecom201503cabforumV4.pdf
kadonotakashi 0:8fdf9a60065b 32 */
kadonotakashi 0:8fdf9a60065b 33
kadonotakashi 0:8fdf9a60065b 34 #if !defined(MBEDTLS_CONFIG_FILE)
kadonotakashi 0:8fdf9a60065b 35 #include "mbedtls/config.h"
kadonotakashi 0:8fdf9a60065b 36 #else
kadonotakashi 0:8fdf9a60065b 37 #include MBEDTLS_CONFIG_FILE
kadonotakashi 0:8fdf9a60065b 38 #endif
kadonotakashi 0:8fdf9a60065b 39
kadonotakashi 0:8fdf9a60065b 40 #if defined(MBEDTLS_X509_CRT_PARSE_C)
kadonotakashi 0:8fdf9a60065b 41
kadonotakashi 0:8fdf9a60065b 42 #include "mbedtls/x509_crt.h"
kadonotakashi 0:8fdf9a60065b 43 #include "mbedtls/oid.h"
kadonotakashi 0:8fdf9a60065b 44 #include "mbedtls/platform_util.h"
kadonotakashi 0:8fdf9a60065b 45
kadonotakashi 0:8fdf9a60065b 46 #include <stdio.h>
kadonotakashi 0:8fdf9a60065b 47 #include <string.h>
kadonotakashi 0:8fdf9a60065b 48
kadonotakashi 0:8fdf9a60065b 49 #if defined(MBEDTLS_PEM_PARSE_C)
kadonotakashi 0:8fdf9a60065b 50 #include "mbedtls/pem.h"
kadonotakashi 0:8fdf9a60065b 51 #endif
kadonotakashi 0:8fdf9a60065b 52
kadonotakashi 0:8fdf9a60065b 53 #if defined(MBEDTLS_PLATFORM_C)
kadonotakashi 0:8fdf9a60065b 54 #include "mbedtls/platform.h"
kadonotakashi 0:8fdf9a60065b 55 #else
kadonotakashi 0:8fdf9a60065b 56 #include <stdlib.h>
kadonotakashi 0:8fdf9a60065b 57 #define mbedtls_free free
kadonotakashi 0:8fdf9a60065b 58 #define mbedtls_calloc calloc
kadonotakashi 0:8fdf9a60065b 59 #define mbedtls_snprintf snprintf
kadonotakashi 0:8fdf9a60065b 60 #endif
kadonotakashi 0:8fdf9a60065b 61
kadonotakashi 0:8fdf9a60065b 62 #if defined(MBEDTLS_THREADING_C)
kadonotakashi 0:8fdf9a60065b 63 #include "mbedtls/threading.h"
kadonotakashi 0:8fdf9a60065b 64 #endif
kadonotakashi 0:8fdf9a60065b 65
kadonotakashi 0:8fdf9a60065b 66 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
kadonotakashi 0:8fdf9a60065b 67 #include <windows.h>
kadonotakashi 0:8fdf9a60065b 68 #else
kadonotakashi 0:8fdf9a60065b 69 #include <time.h>
kadonotakashi 0:8fdf9a60065b 70 #endif
kadonotakashi 0:8fdf9a60065b 71
kadonotakashi 0:8fdf9a60065b 72 #if defined(MBEDTLS_FS_IO)
kadonotakashi 0:8fdf9a60065b 73 #include <stdio.h>
kadonotakashi 0:8fdf9a60065b 74 #if !defined(_WIN32) || defined(EFIX64) || defined(EFI32)
kadonotakashi 0:8fdf9a60065b 75 #include <sys/types.h>
kadonotakashi 0:8fdf9a60065b 76 #include <sys/stat.h>
kadonotakashi 0:8fdf9a60065b 77 #include <dirent.h>
kadonotakashi 0:8fdf9a60065b 78 #endif /* !_WIN32 || EFIX64 || EFI32 */
kadonotakashi 0:8fdf9a60065b 79 #endif
kadonotakashi 0:8fdf9a60065b 80
kadonotakashi 0:8fdf9a60065b 81 /*
kadonotakashi 0:8fdf9a60065b 82 * Item in a verification chain: cert and flags for it
kadonotakashi 0:8fdf9a60065b 83 */
kadonotakashi 0:8fdf9a60065b 84 typedef struct {
kadonotakashi 0:8fdf9a60065b 85 mbedtls_x509_crt *crt;
kadonotakashi 0:8fdf9a60065b 86 uint32_t flags;
kadonotakashi 0:8fdf9a60065b 87 } x509_crt_verify_chain_item;
kadonotakashi 0:8fdf9a60065b 88
kadonotakashi 0:8fdf9a60065b 89 /*
kadonotakashi 0:8fdf9a60065b 90 * Max size of verification chain: end-entity + intermediates + trusted root
kadonotakashi 0:8fdf9a60065b 91 */
kadonotakashi 0:8fdf9a60065b 92 #define X509_MAX_VERIFY_CHAIN_SIZE ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 )
kadonotakashi 0:8fdf9a60065b 93
kadonotakashi 0:8fdf9a60065b 94 /*
kadonotakashi 0:8fdf9a60065b 95 * Default profile
kadonotakashi 0:8fdf9a60065b 96 */
kadonotakashi 0:8fdf9a60065b 97 const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default =
kadonotakashi 0:8fdf9a60065b 98 {
kadonotakashi 0:8fdf9a60065b 99 #if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES)
kadonotakashi 0:8fdf9a60065b 100 /* Allow SHA-1 (weak, but still safe in controlled environments) */
kadonotakashi 0:8fdf9a60065b 101 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) |
kadonotakashi 0:8fdf9a60065b 102 #endif
kadonotakashi 0:8fdf9a60065b 103 /* Only SHA-2 hashes */
kadonotakashi 0:8fdf9a60065b 104 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) |
kadonotakashi 0:8fdf9a60065b 105 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
kadonotakashi 0:8fdf9a60065b 106 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
kadonotakashi 0:8fdf9a60065b 107 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
kadonotakashi 0:8fdf9a60065b 108 0xFFFFFFF, /* Any PK alg */
kadonotakashi 0:8fdf9a60065b 109 0xFFFFFFF, /* Any curve */
kadonotakashi 0:8fdf9a60065b 110 2048,
kadonotakashi 0:8fdf9a60065b 111 };
kadonotakashi 0:8fdf9a60065b 112
kadonotakashi 0:8fdf9a60065b 113 /*
kadonotakashi 0:8fdf9a60065b 114 * Next-default profile
kadonotakashi 0:8fdf9a60065b 115 */
kadonotakashi 0:8fdf9a60065b 116 const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next =
kadonotakashi 0:8fdf9a60065b 117 {
kadonotakashi 0:8fdf9a60065b 118 /* Hashes from SHA-256 and above */
kadonotakashi 0:8fdf9a60065b 119 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
kadonotakashi 0:8fdf9a60065b 120 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
kadonotakashi 0:8fdf9a60065b 121 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
kadonotakashi 0:8fdf9a60065b 122 0xFFFFFFF, /* Any PK alg */
kadonotakashi 0:8fdf9a60065b 123 #if defined(MBEDTLS_ECP_C)
kadonotakashi 0:8fdf9a60065b 124 /* Curves at or above 128-bit security level */
kadonotakashi 0:8fdf9a60065b 125 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) |
kadonotakashi 0:8fdf9a60065b 126 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ) |
kadonotakashi 0:8fdf9a60065b 127 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP521R1 ) |
kadonotakashi 0:8fdf9a60065b 128 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP256R1 ) |
kadonotakashi 0:8fdf9a60065b 129 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP384R1 ) |
kadonotakashi 0:8fdf9a60065b 130 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP512R1 ) |
kadonotakashi 0:8fdf9a60065b 131 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256K1 ),
kadonotakashi 0:8fdf9a60065b 132 #else
kadonotakashi 0:8fdf9a60065b 133 0,
kadonotakashi 0:8fdf9a60065b 134 #endif
kadonotakashi 0:8fdf9a60065b 135 2048,
kadonotakashi 0:8fdf9a60065b 136 };
kadonotakashi 0:8fdf9a60065b 137
kadonotakashi 0:8fdf9a60065b 138 /*
kadonotakashi 0:8fdf9a60065b 139 * NSA Suite B Profile
kadonotakashi 0:8fdf9a60065b 140 */
kadonotakashi 0:8fdf9a60065b 141 const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb =
kadonotakashi 0:8fdf9a60065b 142 {
kadonotakashi 0:8fdf9a60065b 143 /* Only SHA-256 and 384 */
kadonotakashi 0:8fdf9a60065b 144 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
kadonotakashi 0:8fdf9a60065b 145 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ),
kadonotakashi 0:8fdf9a60065b 146 /* Only ECDSA */
kadonotakashi 0:8fdf9a60065b 147 MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ) |
kadonotakashi 0:8fdf9a60065b 148 MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECKEY ),
kadonotakashi 0:8fdf9a60065b 149 #if defined(MBEDTLS_ECP_C)
kadonotakashi 0:8fdf9a60065b 150 /* Only NIST P-256 and P-384 */
kadonotakashi 0:8fdf9a60065b 151 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) |
kadonotakashi 0:8fdf9a60065b 152 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ),
kadonotakashi 0:8fdf9a60065b 153 #else
kadonotakashi 0:8fdf9a60065b 154 0,
kadonotakashi 0:8fdf9a60065b 155 #endif
kadonotakashi 0:8fdf9a60065b 156 0,
kadonotakashi 0:8fdf9a60065b 157 };
kadonotakashi 0:8fdf9a60065b 158
kadonotakashi 0:8fdf9a60065b 159 /*
kadonotakashi 0:8fdf9a60065b 160 * Check md_alg against profile
kadonotakashi 0:8fdf9a60065b 161 * Return 0 if md_alg is acceptable for this profile, -1 otherwise
kadonotakashi 0:8fdf9a60065b 162 */
kadonotakashi 0:8fdf9a60065b 163 static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile,
kadonotakashi 0:8fdf9a60065b 164 mbedtls_md_type_t md_alg )
kadonotakashi 0:8fdf9a60065b 165 {
kadonotakashi 0:8fdf9a60065b 166 if( md_alg == MBEDTLS_MD_NONE )
kadonotakashi 0:8fdf9a60065b 167 return( -1 );
kadonotakashi 0:8fdf9a60065b 168
kadonotakashi 0:8fdf9a60065b 169 if( ( profile->allowed_mds & MBEDTLS_X509_ID_FLAG( md_alg ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 170 return( 0 );
kadonotakashi 0:8fdf9a60065b 171
kadonotakashi 0:8fdf9a60065b 172 return( -1 );
kadonotakashi 0:8fdf9a60065b 173 }
kadonotakashi 0:8fdf9a60065b 174
kadonotakashi 0:8fdf9a60065b 175 /*
kadonotakashi 0:8fdf9a60065b 176 * Check pk_alg against profile
kadonotakashi 0:8fdf9a60065b 177 * Return 0 if pk_alg is acceptable for this profile, -1 otherwise
kadonotakashi 0:8fdf9a60065b 178 */
kadonotakashi 0:8fdf9a60065b 179 static int x509_profile_check_pk_alg( const mbedtls_x509_crt_profile *profile,
kadonotakashi 0:8fdf9a60065b 180 mbedtls_pk_type_t pk_alg )
kadonotakashi 0:8fdf9a60065b 181 {
kadonotakashi 0:8fdf9a60065b 182 if( pk_alg == MBEDTLS_PK_NONE )
kadonotakashi 0:8fdf9a60065b 183 return( -1 );
kadonotakashi 0:8fdf9a60065b 184
kadonotakashi 0:8fdf9a60065b 185 if( ( profile->allowed_pks & MBEDTLS_X509_ID_FLAG( pk_alg ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 186 return( 0 );
kadonotakashi 0:8fdf9a60065b 187
kadonotakashi 0:8fdf9a60065b 188 return( -1 );
kadonotakashi 0:8fdf9a60065b 189 }
kadonotakashi 0:8fdf9a60065b 190
kadonotakashi 0:8fdf9a60065b 191 /*
kadonotakashi 0:8fdf9a60065b 192 * Check key against profile
kadonotakashi 0:8fdf9a60065b 193 * Return 0 if pk is acceptable for this profile, -1 otherwise
kadonotakashi 0:8fdf9a60065b 194 */
kadonotakashi 0:8fdf9a60065b 195 static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile,
kadonotakashi 0:8fdf9a60065b 196 const mbedtls_pk_context *pk )
kadonotakashi 0:8fdf9a60065b 197 {
kadonotakashi 0:8fdf9a60065b 198 const mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type( pk );
kadonotakashi 0:8fdf9a60065b 199
kadonotakashi 0:8fdf9a60065b 200 #if defined(MBEDTLS_RSA_C)
kadonotakashi 0:8fdf9a60065b 201 if( pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS )
kadonotakashi 0:8fdf9a60065b 202 {
kadonotakashi 0:8fdf9a60065b 203 if( mbedtls_pk_get_bitlen( pk ) >= profile->rsa_min_bitlen )
kadonotakashi 0:8fdf9a60065b 204 return( 0 );
kadonotakashi 0:8fdf9a60065b 205
kadonotakashi 0:8fdf9a60065b 206 return( -1 );
kadonotakashi 0:8fdf9a60065b 207 }
kadonotakashi 0:8fdf9a60065b 208 #endif
kadonotakashi 0:8fdf9a60065b 209
kadonotakashi 0:8fdf9a60065b 210 #if defined(MBEDTLS_ECP_C)
kadonotakashi 0:8fdf9a60065b 211 if( pk_alg == MBEDTLS_PK_ECDSA ||
kadonotakashi 0:8fdf9a60065b 212 pk_alg == MBEDTLS_PK_ECKEY ||
kadonotakashi 0:8fdf9a60065b 213 pk_alg == MBEDTLS_PK_ECKEY_DH )
kadonotakashi 0:8fdf9a60065b 214 {
kadonotakashi 0:8fdf9a60065b 215 const mbedtls_ecp_group_id gid = mbedtls_pk_ec( *pk )->grp.id;
kadonotakashi 0:8fdf9a60065b 216
kadonotakashi 0:8fdf9a60065b 217 if( gid == MBEDTLS_ECP_DP_NONE )
kadonotakashi 0:8fdf9a60065b 218 return( -1 );
kadonotakashi 0:8fdf9a60065b 219
kadonotakashi 0:8fdf9a60065b 220 if( ( profile->allowed_curves & MBEDTLS_X509_ID_FLAG( gid ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 221 return( 0 );
kadonotakashi 0:8fdf9a60065b 222
kadonotakashi 0:8fdf9a60065b 223 return( -1 );
kadonotakashi 0:8fdf9a60065b 224 }
kadonotakashi 0:8fdf9a60065b 225 #endif
kadonotakashi 0:8fdf9a60065b 226
kadonotakashi 0:8fdf9a60065b 227 return( -1 );
kadonotakashi 0:8fdf9a60065b 228 }
kadonotakashi 0:8fdf9a60065b 229
kadonotakashi 0:8fdf9a60065b 230 /*
kadonotakashi 0:8fdf9a60065b 231 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
kadonotakashi 0:8fdf9a60065b 232 */
kadonotakashi 0:8fdf9a60065b 233 static int x509_get_version( unsigned char **p,
kadonotakashi 0:8fdf9a60065b 234 const unsigned char *end,
kadonotakashi 0:8fdf9a60065b 235 int *ver )
kadonotakashi 0:8fdf9a60065b 236 {
kadonotakashi 0:8fdf9a60065b 237 int ret;
kadonotakashi 0:8fdf9a60065b 238 size_t len;
kadonotakashi 0:8fdf9a60065b 239
kadonotakashi 0:8fdf9a60065b 240 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
kadonotakashi 0:8fdf9a60065b 241 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 242 {
kadonotakashi 0:8fdf9a60065b 243 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
kadonotakashi 0:8fdf9a60065b 244 {
kadonotakashi 0:8fdf9a60065b 245 *ver = 0;
kadonotakashi 0:8fdf9a60065b 246 return( 0 );
kadonotakashi 0:8fdf9a60065b 247 }
kadonotakashi 0:8fdf9a60065b 248
kadonotakashi 0:8fdf9a60065b 249 return( ret );
kadonotakashi 0:8fdf9a60065b 250 }
kadonotakashi 0:8fdf9a60065b 251
kadonotakashi 0:8fdf9a60065b 252 end = *p + len;
kadonotakashi 0:8fdf9a60065b 253
kadonotakashi 0:8fdf9a60065b 254 if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 255 return( MBEDTLS_ERR_X509_INVALID_VERSION + ret );
kadonotakashi 0:8fdf9a60065b 256
kadonotakashi 0:8fdf9a60065b 257 if( *p != end )
kadonotakashi 0:8fdf9a60065b 258 return( MBEDTLS_ERR_X509_INVALID_VERSION +
kadonotakashi 0:8fdf9a60065b 259 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kadonotakashi 0:8fdf9a60065b 260
kadonotakashi 0:8fdf9a60065b 261 return( 0 );
kadonotakashi 0:8fdf9a60065b 262 }
kadonotakashi 0:8fdf9a60065b 263
kadonotakashi 0:8fdf9a60065b 264 /*
kadonotakashi 0:8fdf9a60065b 265 * Validity ::= SEQUENCE {
kadonotakashi 0:8fdf9a60065b 266 * notBefore Time,
kadonotakashi 0:8fdf9a60065b 267 * notAfter Time }
kadonotakashi 0:8fdf9a60065b 268 */
kadonotakashi 0:8fdf9a60065b 269 static int x509_get_dates( unsigned char **p,
kadonotakashi 0:8fdf9a60065b 270 const unsigned char *end,
kadonotakashi 0:8fdf9a60065b 271 mbedtls_x509_time *from,
kadonotakashi 0:8fdf9a60065b 272 mbedtls_x509_time *to )
kadonotakashi 0:8fdf9a60065b 273 {
kadonotakashi 0:8fdf9a60065b 274 int ret;
kadonotakashi 0:8fdf9a60065b 275 size_t len;
kadonotakashi 0:8fdf9a60065b 276
kadonotakashi 0:8fdf9a60065b 277 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
kadonotakashi 0:8fdf9a60065b 278 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 279 return( MBEDTLS_ERR_X509_INVALID_DATE + ret );
kadonotakashi 0:8fdf9a60065b 280
kadonotakashi 0:8fdf9a60065b 281 end = *p + len;
kadonotakashi 0:8fdf9a60065b 282
kadonotakashi 0:8fdf9a60065b 283 if( ( ret = mbedtls_x509_get_time( p, end, from ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 284 return( ret );
kadonotakashi 0:8fdf9a60065b 285
kadonotakashi 0:8fdf9a60065b 286 if( ( ret = mbedtls_x509_get_time( p, end, to ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 287 return( ret );
kadonotakashi 0:8fdf9a60065b 288
kadonotakashi 0:8fdf9a60065b 289 if( *p != end )
kadonotakashi 0:8fdf9a60065b 290 return( MBEDTLS_ERR_X509_INVALID_DATE +
kadonotakashi 0:8fdf9a60065b 291 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kadonotakashi 0:8fdf9a60065b 292
kadonotakashi 0:8fdf9a60065b 293 return( 0 );
kadonotakashi 0:8fdf9a60065b 294 }
kadonotakashi 0:8fdf9a60065b 295
kadonotakashi 0:8fdf9a60065b 296 /*
kadonotakashi 0:8fdf9a60065b 297 * X.509 v2/v3 unique identifier (not parsed)
kadonotakashi 0:8fdf9a60065b 298 */
kadonotakashi 0:8fdf9a60065b 299 static int x509_get_uid( unsigned char **p,
kadonotakashi 0:8fdf9a60065b 300 const unsigned char *end,
kadonotakashi 0:8fdf9a60065b 301 mbedtls_x509_buf *uid, int n )
kadonotakashi 0:8fdf9a60065b 302 {
kadonotakashi 0:8fdf9a60065b 303 int ret;
kadonotakashi 0:8fdf9a60065b 304
kadonotakashi 0:8fdf9a60065b 305 if( *p == end )
kadonotakashi 0:8fdf9a60065b 306 return( 0 );
kadonotakashi 0:8fdf9a60065b 307
kadonotakashi 0:8fdf9a60065b 308 uid->tag = **p;
kadonotakashi 0:8fdf9a60065b 309
kadonotakashi 0:8fdf9a60065b 310 if( ( ret = mbedtls_asn1_get_tag( p, end, &uid->len,
kadonotakashi 0:8fdf9a60065b 311 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | n ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 312 {
kadonotakashi 0:8fdf9a60065b 313 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
kadonotakashi 0:8fdf9a60065b 314 return( 0 );
kadonotakashi 0:8fdf9a60065b 315
kadonotakashi 0:8fdf9a60065b 316 return( ret );
kadonotakashi 0:8fdf9a60065b 317 }
kadonotakashi 0:8fdf9a60065b 318
kadonotakashi 0:8fdf9a60065b 319 uid->p = *p;
kadonotakashi 0:8fdf9a60065b 320 *p += uid->len;
kadonotakashi 0:8fdf9a60065b 321
kadonotakashi 0:8fdf9a60065b 322 return( 0 );
kadonotakashi 0:8fdf9a60065b 323 }
kadonotakashi 0:8fdf9a60065b 324
kadonotakashi 0:8fdf9a60065b 325 static int x509_get_basic_constraints( unsigned char **p,
kadonotakashi 0:8fdf9a60065b 326 const unsigned char *end,
kadonotakashi 0:8fdf9a60065b 327 int *ca_istrue,
kadonotakashi 0:8fdf9a60065b 328 int *max_pathlen )
kadonotakashi 0:8fdf9a60065b 329 {
kadonotakashi 0:8fdf9a60065b 330 int ret;
kadonotakashi 0:8fdf9a60065b 331 size_t len;
kadonotakashi 0:8fdf9a60065b 332
kadonotakashi 0:8fdf9a60065b 333 /*
kadonotakashi 0:8fdf9a60065b 334 * BasicConstraints ::= SEQUENCE {
kadonotakashi 0:8fdf9a60065b 335 * cA BOOLEAN DEFAULT FALSE,
kadonotakashi 0:8fdf9a60065b 336 * pathLenConstraint INTEGER (0..MAX) OPTIONAL }
kadonotakashi 0:8fdf9a60065b 337 */
kadonotakashi 0:8fdf9a60065b 338 *ca_istrue = 0; /* DEFAULT FALSE */
kadonotakashi 0:8fdf9a60065b 339 *max_pathlen = 0; /* endless */
kadonotakashi 0:8fdf9a60065b 340
kadonotakashi 0:8fdf9a60065b 341 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
kadonotakashi 0:8fdf9a60065b 342 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 343 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kadonotakashi 0:8fdf9a60065b 344
kadonotakashi 0:8fdf9a60065b 345 if( *p == end )
kadonotakashi 0:8fdf9a60065b 346 return( 0 );
kadonotakashi 0:8fdf9a60065b 347
kadonotakashi 0:8fdf9a60065b 348 if( ( ret = mbedtls_asn1_get_bool( p, end, ca_istrue ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 349 {
kadonotakashi 0:8fdf9a60065b 350 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
kadonotakashi 0:8fdf9a60065b 351 ret = mbedtls_asn1_get_int( p, end, ca_istrue );
kadonotakashi 0:8fdf9a60065b 352
kadonotakashi 0:8fdf9a60065b 353 if( ret != 0 )
kadonotakashi 0:8fdf9a60065b 354 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kadonotakashi 0:8fdf9a60065b 355
kadonotakashi 0:8fdf9a60065b 356 if( *ca_istrue != 0 )
kadonotakashi 0:8fdf9a60065b 357 *ca_istrue = 1;
kadonotakashi 0:8fdf9a60065b 358 }
kadonotakashi 0:8fdf9a60065b 359
kadonotakashi 0:8fdf9a60065b 360 if( *p == end )
kadonotakashi 0:8fdf9a60065b 361 return( 0 );
kadonotakashi 0:8fdf9a60065b 362
kadonotakashi 0:8fdf9a60065b 363 if( ( ret = mbedtls_asn1_get_int( p, end, max_pathlen ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 364 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kadonotakashi 0:8fdf9a60065b 365
kadonotakashi 0:8fdf9a60065b 366 if( *p != end )
kadonotakashi 0:8fdf9a60065b 367 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kadonotakashi 0:8fdf9a60065b 368 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kadonotakashi 0:8fdf9a60065b 369
kadonotakashi 0:8fdf9a60065b 370 (*max_pathlen)++;
kadonotakashi 0:8fdf9a60065b 371
kadonotakashi 0:8fdf9a60065b 372 return( 0 );
kadonotakashi 0:8fdf9a60065b 373 }
kadonotakashi 0:8fdf9a60065b 374
kadonotakashi 0:8fdf9a60065b 375 static int x509_get_ns_cert_type( unsigned char **p,
kadonotakashi 0:8fdf9a60065b 376 const unsigned char *end,
kadonotakashi 0:8fdf9a60065b 377 unsigned char *ns_cert_type)
kadonotakashi 0:8fdf9a60065b 378 {
kadonotakashi 0:8fdf9a60065b 379 int ret;
kadonotakashi 0:8fdf9a60065b 380 mbedtls_x509_bitstring bs = { 0, 0, NULL };
kadonotakashi 0:8fdf9a60065b 381
kadonotakashi 0:8fdf9a60065b 382 if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 383 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kadonotakashi 0:8fdf9a60065b 384
kadonotakashi 0:8fdf9a60065b 385 if( bs.len != 1 )
kadonotakashi 0:8fdf9a60065b 386 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kadonotakashi 0:8fdf9a60065b 387 MBEDTLS_ERR_ASN1_INVALID_LENGTH );
kadonotakashi 0:8fdf9a60065b 388
kadonotakashi 0:8fdf9a60065b 389 /* Get actual bitstring */
kadonotakashi 0:8fdf9a60065b 390 *ns_cert_type = *bs.p;
kadonotakashi 0:8fdf9a60065b 391 return( 0 );
kadonotakashi 0:8fdf9a60065b 392 }
kadonotakashi 0:8fdf9a60065b 393
kadonotakashi 0:8fdf9a60065b 394 static int x509_get_key_usage( unsigned char **p,
kadonotakashi 0:8fdf9a60065b 395 const unsigned char *end,
kadonotakashi 0:8fdf9a60065b 396 unsigned int *key_usage)
kadonotakashi 0:8fdf9a60065b 397 {
kadonotakashi 0:8fdf9a60065b 398 int ret;
kadonotakashi 0:8fdf9a60065b 399 size_t i;
kadonotakashi 0:8fdf9a60065b 400 mbedtls_x509_bitstring bs = { 0, 0, NULL };
kadonotakashi 0:8fdf9a60065b 401
kadonotakashi 0:8fdf9a60065b 402 if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 403 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kadonotakashi 0:8fdf9a60065b 404
kadonotakashi 0:8fdf9a60065b 405 if( bs.len < 1 )
kadonotakashi 0:8fdf9a60065b 406 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kadonotakashi 0:8fdf9a60065b 407 MBEDTLS_ERR_ASN1_INVALID_LENGTH );
kadonotakashi 0:8fdf9a60065b 408
kadonotakashi 0:8fdf9a60065b 409 /* Get actual bitstring */
kadonotakashi 0:8fdf9a60065b 410 *key_usage = 0;
kadonotakashi 0:8fdf9a60065b 411 for( i = 0; i < bs.len && i < sizeof( unsigned int ); i++ )
kadonotakashi 0:8fdf9a60065b 412 {
kadonotakashi 0:8fdf9a60065b 413 *key_usage |= (unsigned int) bs.p[i] << (8*i);
kadonotakashi 0:8fdf9a60065b 414 }
kadonotakashi 0:8fdf9a60065b 415
kadonotakashi 0:8fdf9a60065b 416 return( 0 );
kadonotakashi 0:8fdf9a60065b 417 }
kadonotakashi 0:8fdf9a60065b 418
kadonotakashi 0:8fdf9a60065b 419 /*
kadonotakashi 0:8fdf9a60065b 420 * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
kadonotakashi 0:8fdf9a60065b 421 *
kadonotakashi 0:8fdf9a60065b 422 * KeyPurposeId ::= OBJECT IDENTIFIER
kadonotakashi 0:8fdf9a60065b 423 */
kadonotakashi 0:8fdf9a60065b 424 static int x509_get_ext_key_usage( unsigned char **p,
kadonotakashi 0:8fdf9a60065b 425 const unsigned char *end,
kadonotakashi 0:8fdf9a60065b 426 mbedtls_x509_sequence *ext_key_usage)
kadonotakashi 0:8fdf9a60065b 427 {
kadonotakashi 0:8fdf9a60065b 428 int ret;
kadonotakashi 0:8fdf9a60065b 429
kadonotakashi 0:8fdf9a60065b 430 if( ( ret = mbedtls_asn1_get_sequence_of( p, end, ext_key_usage, MBEDTLS_ASN1_OID ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 431 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kadonotakashi 0:8fdf9a60065b 432
kadonotakashi 0:8fdf9a60065b 433 /* Sequence length must be >= 1 */
kadonotakashi 0:8fdf9a60065b 434 if( ext_key_usage->buf.p == NULL )
kadonotakashi 0:8fdf9a60065b 435 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kadonotakashi 0:8fdf9a60065b 436 MBEDTLS_ERR_ASN1_INVALID_LENGTH );
kadonotakashi 0:8fdf9a60065b 437
kadonotakashi 0:8fdf9a60065b 438 return( 0 );
kadonotakashi 0:8fdf9a60065b 439 }
kadonotakashi 0:8fdf9a60065b 440
kadonotakashi 0:8fdf9a60065b 441 /*
kadonotakashi 0:8fdf9a60065b 442 * SubjectAltName ::= GeneralNames
kadonotakashi 0:8fdf9a60065b 443 *
kadonotakashi 0:8fdf9a60065b 444 * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
kadonotakashi 0:8fdf9a60065b 445 *
kadonotakashi 0:8fdf9a60065b 446 * GeneralName ::= CHOICE {
kadonotakashi 0:8fdf9a60065b 447 * otherName [0] OtherName,
kadonotakashi 0:8fdf9a60065b 448 * rfc822Name [1] IA5String,
kadonotakashi 0:8fdf9a60065b 449 * dNSName [2] IA5String,
kadonotakashi 0:8fdf9a60065b 450 * x400Address [3] ORAddress,
kadonotakashi 0:8fdf9a60065b 451 * directoryName [4] Name,
kadonotakashi 0:8fdf9a60065b 452 * ediPartyName [5] EDIPartyName,
kadonotakashi 0:8fdf9a60065b 453 * uniformResourceIdentifier [6] IA5String,
kadonotakashi 0:8fdf9a60065b 454 * iPAddress [7] OCTET STRING,
kadonotakashi 0:8fdf9a60065b 455 * registeredID [8] OBJECT IDENTIFIER }
kadonotakashi 0:8fdf9a60065b 456 *
kadonotakashi 0:8fdf9a60065b 457 * OtherName ::= SEQUENCE {
kadonotakashi 0:8fdf9a60065b 458 * type-id OBJECT IDENTIFIER,
kadonotakashi 0:8fdf9a60065b 459 * value [0] EXPLICIT ANY DEFINED BY type-id }
kadonotakashi 0:8fdf9a60065b 460 *
kadonotakashi 0:8fdf9a60065b 461 * EDIPartyName ::= SEQUENCE {
kadonotakashi 0:8fdf9a60065b 462 * nameAssigner [0] DirectoryString OPTIONAL,
kadonotakashi 0:8fdf9a60065b 463 * partyName [1] DirectoryString }
kadonotakashi 0:8fdf9a60065b 464 *
kadonotakashi 0:8fdf9a60065b 465 * NOTE: we only parse and use dNSName at this point.
kadonotakashi 0:8fdf9a60065b 466 */
kadonotakashi 0:8fdf9a60065b 467 static int x509_get_subject_alt_name( unsigned char **p,
kadonotakashi 0:8fdf9a60065b 468 const unsigned char *end,
kadonotakashi 0:8fdf9a60065b 469 mbedtls_x509_sequence *subject_alt_name )
kadonotakashi 0:8fdf9a60065b 470 {
kadonotakashi 0:8fdf9a60065b 471 int ret;
kadonotakashi 0:8fdf9a60065b 472 size_t len, tag_len;
kadonotakashi 0:8fdf9a60065b 473 mbedtls_asn1_buf *buf;
kadonotakashi 0:8fdf9a60065b 474 unsigned char tag;
kadonotakashi 0:8fdf9a60065b 475 mbedtls_asn1_sequence *cur = subject_alt_name;
kadonotakashi 0:8fdf9a60065b 476
kadonotakashi 0:8fdf9a60065b 477 /* Get main sequence tag */
kadonotakashi 0:8fdf9a60065b 478 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
kadonotakashi 0:8fdf9a60065b 479 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 480 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kadonotakashi 0:8fdf9a60065b 481
kadonotakashi 0:8fdf9a60065b 482 if( *p + len != end )
kadonotakashi 0:8fdf9a60065b 483 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kadonotakashi 0:8fdf9a60065b 484 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kadonotakashi 0:8fdf9a60065b 485
kadonotakashi 0:8fdf9a60065b 486 while( *p < end )
kadonotakashi 0:8fdf9a60065b 487 {
kadonotakashi 0:8fdf9a60065b 488 if( ( end - *p ) < 1 )
kadonotakashi 0:8fdf9a60065b 489 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kadonotakashi 0:8fdf9a60065b 490 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
kadonotakashi 0:8fdf9a60065b 491
kadonotakashi 0:8fdf9a60065b 492 tag = **p;
kadonotakashi 0:8fdf9a60065b 493 (*p)++;
kadonotakashi 0:8fdf9a60065b 494 if( ( ret = mbedtls_asn1_get_len( p, end, &tag_len ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 495 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kadonotakashi 0:8fdf9a60065b 496
kadonotakashi 0:8fdf9a60065b 497 if( ( tag & MBEDTLS_ASN1_TAG_CLASS_MASK ) !=
kadonotakashi 0:8fdf9a60065b 498 MBEDTLS_ASN1_CONTEXT_SPECIFIC )
kadonotakashi 0:8fdf9a60065b 499 {
kadonotakashi 0:8fdf9a60065b 500 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kadonotakashi 0:8fdf9a60065b 501 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
kadonotakashi 0:8fdf9a60065b 502 }
kadonotakashi 0:8fdf9a60065b 503
kadonotakashi 0:8fdf9a60065b 504 /* Skip everything but DNS name */
kadonotakashi 0:8fdf9a60065b 505 if( tag != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2 ) )
kadonotakashi 0:8fdf9a60065b 506 {
kadonotakashi 0:8fdf9a60065b 507 *p += tag_len;
kadonotakashi 0:8fdf9a60065b 508 continue;
kadonotakashi 0:8fdf9a60065b 509 }
kadonotakashi 0:8fdf9a60065b 510
kadonotakashi 0:8fdf9a60065b 511 /* Allocate and assign next pointer */
kadonotakashi 0:8fdf9a60065b 512 if( cur->buf.p != NULL )
kadonotakashi 0:8fdf9a60065b 513 {
kadonotakashi 0:8fdf9a60065b 514 if( cur->next != NULL )
kadonotakashi 0:8fdf9a60065b 515 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS );
kadonotakashi 0:8fdf9a60065b 516
kadonotakashi 0:8fdf9a60065b 517 cur->next = mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) );
kadonotakashi 0:8fdf9a60065b 518
kadonotakashi 0:8fdf9a60065b 519 if( cur->next == NULL )
kadonotakashi 0:8fdf9a60065b 520 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kadonotakashi 0:8fdf9a60065b 521 MBEDTLS_ERR_ASN1_ALLOC_FAILED );
kadonotakashi 0:8fdf9a60065b 522
kadonotakashi 0:8fdf9a60065b 523 cur = cur->next;
kadonotakashi 0:8fdf9a60065b 524 }
kadonotakashi 0:8fdf9a60065b 525
kadonotakashi 0:8fdf9a60065b 526 buf = &(cur->buf);
kadonotakashi 0:8fdf9a60065b 527 buf->tag = tag;
kadonotakashi 0:8fdf9a60065b 528 buf->p = *p;
kadonotakashi 0:8fdf9a60065b 529 buf->len = tag_len;
kadonotakashi 0:8fdf9a60065b 530 *p += buf->len;
kadonotakashi 0:8fdf9a60065b 531 }
kadonotakashi 0:8fdf9a60065b 532
kadonotakashi 0:8fdf9a60065b 533 /* Set final sequence entry's next pointer to NULL */
kadonotakashi 0:8fdf9a60065b 534 cur->next = NULL;
kadonotakashi 0:8fdf9a60065b 535
kadonotakashi 0:8fdf9a60065b 536 if( *p != end )
kadonotakashi 0:8fdf9a60065b 537 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kadonotakashi 0:8fdf9a60065b 538 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kadonotakashi 0:8fdf9a60065b 539
kadonotakashi 0:8fdf9a60065b 540 return( 0 );
kadonotakashi 0:8fdf9a60065b 541 }
kadonotakashi 0:8fdf9a60065b 542
kadonotakashi 0:8fdf9a60065b 543 /*
kadonotakashi 0:8fdf9a60065b 544 * X.509 v3 extensions
kadonotakashi 0:8fdf9a60065b 545 *
kadonotakashi 0:8fdf9a60065b 546 */
kadonotakashi 0:8fdf9a60065b 547 static int x509_get_crt_ext( unsigned char **p,
kadonotakashi 0:8fdf9a60065b 548 const unsigned char *end,
kadonotakashi 0:8fdf9a60065b 549 mbedtls_x509_crt *crt )
kadonotakashi 0:8fdf9a60065b 550 {
kadonotakashi 0:8fdf9a60065b 551 int ret;
kadonotakashi 0:8fdf9a60065b 552 size_t len;
kadonotakashi 0:8fdf9a60065b 553 unsigned char *end_ext_data, *end_ext_octet;
kadonotakashi 0:8fdf9a60065b 554
kadonotakashi 0:8fdf9a60065b 555 if( ( ret = mbedtls_x509_get_ext( p, end, &crt->v3_ext, 3 ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 556 {
kadonotakashi 0:8fdf9a60065b 557 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
kadonotakashi 0:8fdf9a60065b 558 return( 0 );
kadonotakashi 0:8fdf9a60065b 559
kadonotakashi 0:8fdf9a60065b 560 return( ret );
kadonotakashi 0:8fdf9a60065b 561 }
kadonotakashi 0:8fdf9a60065b 562
kadonotakashi 0:8fdf9a60065b 563 while( *p < end )
kadonotakashi 0:8fdf9a60065b 564 {
kadonotakashi 0:8fdf9a60065b 565 /*
kadonotakashi 0:8fdf9a60065b 566 * Extension ::= SEQUENCE {
kadonotakashi 0:8fdf9a60065b 567 * extnID OBJECT IDENTIFIER,
kadonotakashi 0:8fdf9a60065b 568 * critical BOOLEAN DEFAULT FALSE,
kadonotakashi 0:8fdf9a60065b 569 * extnValue OCTET STRING }
kadonotakashi 0:8fdf9a60065b 570 */
kadonotakashi 0:8fdf9a60065b 571 mbedtls_x509_buf extn_oid = {0, 0, NULL};
kadonotakashi 0:8fdf9a60065b 572 int is_critical = 0; /* DEFAULT FALSE */
kadonotakashi 0:8fdf9a60065b 573 int ext_type = 0;
kadonotakashi 0:8fdf9a60065b 574
kadonotakashi 0:8fdf9a60065b 575 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
kadonotakashi 0:8fdf9a60065b 576 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 577 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kadonotakashi 0:8fdf9a60065b 578
kadonotakashi 0:8fdf9a60065b 579 end_ext_data = *p + len;
kadonotakashi 0:8fdf9a60065b 580
kadonotakashi 0:8fdf9a60065b 581 /* Get extension ID */
kadonotakashi 0:8fdf9a60065b 582 if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &extn_oid.len,
kadonotakashi 0:8fdf9a60065b 583 MBEDTLS_ASN1_OID ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 584 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kadonotakashi 0:8fdf9a60065b 585
kadonotakashi 0:8fdf9a60065b 586 extn_oid.tag = MBEDTLS_ASN1_OID;
kadonotakashi 0:8fdf9a60065b 587 extn_oid.p = *p;
kadonotakashi 0:8fdf9a60065b 588 *p += extn_oid.len;
kadonotakashi 0:8fdf9a60065b 589
kadonotakashi 0:8fdf9a60065b 590 /* Get optional critical */
kadonotakashi 0:8fdf9a60065b 591 if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 &&
kadonotakashi 0:8fdf9a60065b 592 ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) )
kadonotakashi 0:8fdf9a60065b 593 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kadonotakashi 0:8fdf9a60065b 594
kadonotakashi 0:8fdf9a60065b 595 /* Data should be octet string type */
kadonotakashi 0:8fdf9a60065b 596 if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len,
kadonotakashi 0:8fdf9a60065b 597 MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 598 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kadonotakashi 0:8fdf9a60065b 599
kadonotakashi 0:8fdf9a60065b 600 end_ext_octet = *p + len;
kadonotakashi 0:8fdf9a60065b 601
kadonotakashi 0:8fdf9a60065b 602 if( end_ext_octet != end_ext_data )
kadonotakashi 0:8fdf9a60065b 603 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kadonotakashi 0:8fdf9a60065b 604 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kadonotakashi 0:8fdf9a60065b 605
kadonotakashi 0:8fdf9a60065b 606 /*
kadonotakashi 0:8fdf9a60065b 607 * Detect supported extensions
kadonotakashi 0:8fdf9a60065b 608 */
kadonotakashi 0:8fdf9a60065b 609 ret = mbedtls_oid_get_x509_ext_type( &extn_oid, &ext_type );
kadonotakashi 0:8fdf9a60065b 610
kadonotakashi 0:8fdf9a60065b 611 if( ret != 0 )
kadonotakashi 0:8fdf9a60065b 612 {
kadonotakashi 0:8fdf9a60065b 613 /* No parser found, skip extension */
kadonotakashi 0:8fdf9a60065b 614 *p = end_ext_octet;
kadonotakashi 0:8fdf9a60065b 615
kadonotakashi 0:8fdf9a60065b 616 #if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
kadonotakashi 0:8fdf9a60065b 617 if( is_critical )
kadonotakashi 0:8fdf9a60065b 618 {
kadonotakashi 0:8fdf9a60065b 619 /* Data is marked as critical: fail */
kadonotakashi 0:8fdf9a60065b 620 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kadonotakashi 0:8fdf9a60065b 621 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
kadonotakashi 0:8fdf9a60065b 622 }
kadonotakashi 0:8fdf9a60065b 623 #endif
kadonotakashi 0:8fdf9a60065b 624 continue;
kadonotakashi 0:8fdf9a60065b 625 }
kadonotakashi 0:8fdf9a60065b 626
kadonotakashi 0:8fdf9a60065b 627 /* Forbid repeated extensions */
kadonotakashi 0:8fdf9a60065b 628 if( ( crt->ext_types & ext_type ) != 0 )
kadonotakashi 0:8fdf9a60065b 629 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS );
kadonotakashi 0:8fdf9a60065b 630
kadonotakashi 0:8fdf9a60065b 631 crt->ext_types |= ext_type;
kadonotakashi 0:8fdf9a60065b 632
kadonotakashi 0:8fdf9a60065b 633 switch( ext_type )
kadonotakashi 0:8fdf9a60065b 634 {
kadonotakashi 0:8fdf9a60065b 635 case MBEDTLS_X509_EXT_BASIC_CONSTRAINTS:
kadonotakashi 0:8fdf9a60065b 636 /* Parse basic constraints */
kadonotakashi 0:8fdf9a60065b 637 if( ( ret = x509_get_basic_constraints( p, end_ext_octet,
kadonotakashi 0:8fdf9a60065b 638 &crt->ca_istrue, &crt->max_pathlen ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 639 return( ret );
kadonotakashi 0:8fdf9a60065b 640 break;
kadonotakashi 0:8fdf9a60065b 641
kadonotakashi 0:8fdf9a60065b 642 case MBEDTLS_X509_EXT_KEY_USAGE:
kadonotakashi 0:8fdf9a60065b 643 /* Parse key usage */
kadonotakashi 0:8fdf9a60065b 644 if( ( ret = x509_get_key_usage( p, end_ext_octet,
kadonotakashi 0:8fdf9a60065b 645 &crt->key_usage ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 646 return( ret );
kadonotakashi 0:8fdf9a60065b 647 break;
kadonotakashi 0:8fdf9a60065b 648
kadonotakashi 0:8fdf9a60065b 649 case MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE:
kadonotakashi 0:8fdf9a60065b 650 /* Parse extended key usage */
kadonotakashi 0:8fdf9a60065b 651 if( ( ret = x509_get_ext_key_usage( p, end_ext_octet,
kadonotakashi 0:8fdf9a60065b 652 &crt->ext_key_usage ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 653 return( ret );
kadonotakashi 0:8fdf9a60065b 654 break;
kadonotakashi 0:8fdf9a60065b 655
kadonotakashi 0:8fdf9a60065b 656 case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME:
kadonotakashi 0:8fdf9a60065b 657 /* Parse subject alt name */
kadonotakashi 0:8fdf9a60065b 658 if( ( ret = x509_get_subject_alt_name( p, end_ext_octet,
kadonotakashi 0:8fdf9a60065b 659 &crt->subject_alt_names ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 660 return( ret );
kadonotakashi 0:8fdf9a60065b 661 break;
kadonotakashi 0:8fdf9a60065b 662
kadonotakashi 0:8fdf9a60065b 663 case MBEDTLS_X509_EXT_NS_CERT_TYPE:
kadonotakashi 0:8fdf9a60065b 664 /* Parse netscape certificate type */
kadonotakashi 0:8fdf9a60065b 665 if( ( ret = x509_get_ns_cert_type( p, end_ext_octet,
kadonotakashi 0:8fdf9a60065b 666 &crt->ns_cert_type ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 667 return( ret );
kadonotakashi 0:8fdf9a60065b 668 break;
kadonotakashi 0:8fdf9a60065b 669
kadonotakashi 0:8fdf9a60065b 670 default:
kadonotakashi 0:8fdf9a60065b 671 return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
kadonotakashi 0:8fdf9a60065b 672 }
kadonotakashi 0:8fdf9a60065b 673 }
kadonotakashi 0:8fdf9a60065b 674
kadonotakashi 0:8fdf9a60065b 675 if( *p != end )
kadonotakashi 0:8fdf9a60065b 676 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kadonotakashi 0:8fdf9a60065b 677 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kadonotakashi 0:8fdf9a60065b 678
kadonotakashi 0:8fdf9a60065b 679 return( 0 );
kadonotakashi 0:8fdf9a60065b 680 }
kadonotakashi 0:8fdf9a60065b 681
kadonotakashi 0:8fdf9a60065b 682 /*
kadonotakashi 0:8fdf9a60065b 683 * Parse and fill a single X.509 certificate in DER format
kadonotakashi 0:8fdf9a60065b 684 */
kadonotakashi 0:8fdf9a60065b 685 static int x509_crt_parse_der_core( mbedtls_x509_crt *crt, const unsigned char *buf,
kadonotakashi 0:8fdf9a60065b 686 size_t buflen )
kadonotakashi 0:8fdf9a60065b 687 {
kadonotakashi 0:8fdf9a60065b 688 int ret;
kadonotakashi 0:8fdf9a60065b 689 size_t len;
kadonotakashi 0:8fdf9a60065b 690 unsigned char *p, *end, *crt_end;
kadonotakashi 0:8fdf9a60065b 691 mbedtls_x509_buf sig_params1, sig_params2, sig_oid2;
kadonotakashi 0:8fdf9a60065b 692
kadonotakashi 0:8fdf9a60065b 693 memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) );
kadonotakashi 0:8fdf9a60065b 694 memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) );
kadonotakashi 0:8fdf9a60065b 695 memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) );
kadonotakashi 0:8fdf9a60065b 696
kadonotakashi 0:8fdf9a60065b 697 /*
kadonotakashi 0:8fdf9a60065b 698 * Check for valid input
kadonotakashi 0:8fdf9a60065b 699 */
kadonotakashi 0:8fdf9a60065b 700 if( crt == NULL || buf == NULL )
kadonotakashi 0:8fdf9a60065b 701 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
kadonotakashi 0:8fdf9a60065b 702
kadonotakashi 0:8fdf9a60065b 703 // Use the original buffer until we figure out actual length
kadonotakashi 0:8fdf9a60065b 704 p = (unsigned char*) buf;
kadonotakashi 0:8fdf9a60065b 705 len = buflen;
kadonotakashi 0:8fdf9a60065b 706 end = p + len;
kadonotakashi 0:8fdf9a60065b 707
kadonotakashi 0:8fdf9a60065b 708 /*
kadonotakashi 0:8fdf9a60065b 709 * Certificate ::= SEQUENCE {
kadonotakashi 0:8fdf9a60065b 710 * tbsCertificate TBSCertificate,
kadonotakashi 0:8fdf9a60065b 711 * signatureAlgorithm AlgorithmIdentifier,
kadonotakashi 0:8fdf9a60065b 712 * signatureValue BIT STRING }
kadonotakashi 0:8fdf9a60065b 713 */
kadonotakashi 0:8fdf9a60065b 714 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
kadonotakashi 0:8fdf9a60065b 715 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 716 {
kadonotakashi 0:8fdf9a60065b 717 mbedtls_x509_crt_free( crt );
kadonotakashi 0:8fdf9a60065b 718 return( MBEDTLS_ERR_X509_INVALID_FORMAT );
kadonotakashi 0:8fdf9a60065b 719 }
kadonotakashi 0:8fdf9a60065b 720
kadonotakashi 0:8fdf9a60065b 721 if( len > (size_t) ( end - p ) )
kadonotakashi 0:8fdf9a60065b 722 {
kadonotakashi 0:8fdf9a60065b 723 mbedtls_x509_crt_free( crt );
kadonotakashi 0:8fdf9a60065b 724 return( MBEDTLS_ERR_X509_INVALID_FORMAT +
kadonotakashi 0:8fdf9a60065b 725 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kadonotakashi 0:8fdf9a60065b 726 }
kadonotakashi 0:8fdf9a60065b 727 crt_end = p + len;
kadonotakashi 0:8fdf9a60065b 728
kadonotakashi 0:8fdf9a60065b 729 // Create and populate a new buffer for the raw field
kadonotakashi 0:8fdf9a60065b 730 crt->raw.len = crt_end - buf;
kadonotakashi 0:8fdf9a60065b 731 crt->raw.p = p = mbedtls_calloc( 1, crt->raw.len );
kadonotakashi 0:8fdf9a60065b 732 if( p == NULL )
kadonotakashi 0:8fdf9a60065b 733 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
kadonotakashi 0:8fdf9a60065b 734
kadonotakashi 0:8fdf9a60065b 735 memcpy( p, buf, crt->raw.len );
kadonotakashi 0:8fdf9a60065b 736
kadonotakashi 0:8fdf9a60065b 737 // Direct pointers to the new buffer
kadonotakashi 0:8fdf9a60065b 738 p += crt->raw.len - len;
kadonotakashi 0:8fdf9a60065b 739 end = crt_end = p + len;
kadonotakashi 0:8fdf9a60065b 740
kadonotakashi 0:8fdf9a60065b 741 /*
kadonotakashi 0:8fdf9a60065b 742 * TBSCertificate ::= SEQUENCE {
kadonotakashi 0:8fdf9a60065b 743 */
kadonotakashi 0:8fdf9a60065b 744 crt->tbs.p = p;
kadonotakashi 0:8fdf9a60065b 745
kadonotakashi 0:8fdf9a60065b 746 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
kadonotakashi 0:8fdf9a60065b 747 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 748 {
kadonotakashi 0:8fdf9a60065b 749 mbedtls_x509_crt_free( crt );
kadonotakashi 0:8fdf9a60065b 750 return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
kadonotakashi 0:8fdf9a60065b 751 }
kadonotakashi 0:8fdf9a60065b 752
kadonotakashi 0:8fdf9a60065b 753 end = p + len;
kadonotakashi 0:8fdf9a60065b 754 crt->tbs.len = end - crt->tbs.p;
kadonotakashi 0:8fdf9a60065b 755
kadonotakashi 0:8fdf9a60065b 756 /*
kadonotakashi 0:8fdf9a60065b 757 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
kadonotakashi 0:8fdf9a60065b 758 *
kadonotakashi 0:8fdf9a60065b 759 * CertificateSerialNumber ::= INTEGER
kadonotakashi 0:8fdf9a60065b 760 *
kadonotakashi 0:8fdf9a60065b 761 * signature AlgorithmIdentifier
kadonotakashi 0:8fdf9a60065b 762 */
kadonotakashi 0:8fdf9a60065b 763 if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 ||
kadonotakashi 0:8fdf9a60065b 764 ( ret = mbedtls_x509_get_serial( &p, end, &crt->serial ) ) != 0 ||
kadonotakashi 0:8fdf9a60065b 765 ( ret = mbedtls_x509_get_alg( &p, end, &crt->sig_oid,
kadonotakashi 0:8fdf9a60065b 766 &sig_params1 ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 767 {
kadonotakashi 0:8fdf9a60065b 768 mbedtls_x509_crt_free( crt );
kadonotakashi 0:8fdf9a60065b 769 return( ret );
kadonotakashi 0:8fdf9a60065b 770 }
kadonotakashi 0:8fdf9a60065b 771
kadonotakashi 0:8fdf9a60065b 772 if( crt->version < 0 || crt->version > 2 )
kadonotakashi 0:8fdf9a60065b 773 {
kadonotakashi 0:8fdf9a60065b 774 mbedtls_x509_crt_free( crt );
kadonotakashi 0:8fdf9a60065b 775 return( MBEDTLS_ERR_X509_UNKNOWN_VERSION );
kadonotakashi 0:8fdf9a60065b 776 }
kadonotakashi 0:8fdf9a60065b 777
kadonotakashi 0:8fdf9a60065b 778 crt->version++;
kadonotakashi 0:8fdf9a60065b 779
kadonotakashi 0:8fdf9a60065b 780 if( ( ret = mbedtls_x509_get_sig_alg( &crt->sig_oid, &sig_params1,
kadonotakashi 0:8fdf9a60065b 781 &crt->sig_md, &crt->sig_pk,
kadonotakashi 0:8fdf9a60065b 782 &crt->sig_opts ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 783 {
kadonotakashi 0:8fdf9a60065b 784 mbedtls_x509_crt_free( crt );
kadonotakashi 0:8fdf9a60065b 785 return( ret );
kadonotakashi 0:8fdf9a60065b 786 }
kadonotakashi 0:8fdf9a60065b 787
kadonotakashi 0:8fdf9a60065b 788 /*
kadonotakashi 0:8fdf9a60065b 789 * issuer Name
kadonotakashi 0:8fdf9a60065b 790 */
kadonotakashi 0:8fdf9a60065b 791 crt->issuer_raw.p = p;
kadonotakashi 0:8fdf9a60065b 792
kadonotakashi 0:8fdf9a60065b 793 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
kadonotakashi 0:8fdf9a60065b 794 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 795 {
kadonotakashi 0:8fdf9a60065b 796 mbedtls_x509_crt_free( crt );
kadonotakashi 0:8fdf9a60065b 797 return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
kadonotakashi 0:8fdf9a60065b 798 }
kadonotakashi 0:8fdf9a60065b 799
kadonotakashi 0:8fdf9a60065b 800 if( ( ret = mbedtls_x509_get_name( &p, p + len, &crt->issuer ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 801 {
kadonotakashi 0:8fdf9a60065b 802 mbedtls_x509_crt_free( crt );
kadonotakashi 0:8fdf9a60065b 803 return( ret );
kadonotakashi 0:8fdf9a60065b 804 }
kadonotakashi 0:8fdf9a60065b 805
kadonotakashi 0:8fdf9a60065b 806 crt->issuer_raw.len = p - crt->issuer_raw.p;
kadonotakashi 0:8fdf9a60065b 807
kadonotakashi 0:8fdf9a60065b 808 /*
kadonotakashi 0:8fdf9a60065b 809 * Validity ::= SEQUENCE {
kadonotakashi 0:8fdf9a60065b 810 * notBefore Time,
kadonotakashi 0:8fdf9a60065b 811 * notAfter Time }
kadonotakashi 0:8fdf9a60065b 812 *
kadonotakashi 0:8fdf9a60065b 813 */
kadonotakashi 0:8fdf9a60065b 814 if( ( ret = x509_get_dates( &p, end, &crt->valid_from,
kadonotakashi 0:8fdf9a60065b 815 &crt->valid_to ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 816 {
kadonotakashi 0:8fdf9a60065b 817 mbedtls_x509_crt_free( crt );
kadonotakashi 0:8fdf9a60065b 818 return( ret );
kadonotakashi 0:8fdf9a60065b 819 }
kadonotakashi 0:8fdf9a60065b 820
kadonotakashi 0:8fdf9a60065b 821 /*
kadonotakashi 0:8fdf9a60065b 822 * subject Name
kadonotakashi 0:8fdf9a60065b 823 */
kadonotakashi 0:8fdf9a60065b 824 crt->subject_raw.p = p;
kadonotakashi 0:8fdf9a60065b 825
kadonotakashi 0:8fdf9a60065b 826 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
kadonotakashi 0:8fdf9a60065b 827 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 828 {
kadonotakashi 0:8fdf9a60065b 829 mbedtls_x509_crt_free( crt );
kadonotakashi 0:8fdf9a60065b 830 return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
kadonotakashi 0:8fdf9a60065b 831 }
kadonotakashi 0:8fdf9a60065b 832
kadonotakashi 0:8fdf9a60065b 833 if( len && ( ret = mbedtls_x509_get_name( &p, p + len, &crt->subject ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 834 {
kadonotakashi 0:8fdf9a60065b 835 mbedtls_x509_crt_free( crt );
kadonotakashi 0:8fdf9a60065b 836 return( ret );
kadonotakashi 0:8fdf9a60065b 837 }
kadonotakashi 0:8fdf9a60065b 838
kadonotakashi 0:8fdf9a60065b 839 crt->subject_raw.len = p - crt->subject_raw.p;
kadonotakashi 0:8fdf9a60065b 840
kadonotakashi 0:8fdf9a60065b 841 /*
kadonotakashi 0:8fdf9a60065b 842 * SubjectPublicKeyInfo
kadonotakashi 0:8fdf9a60065b 843 */
kadonotakashi 0:8fdf9a60065b 844 if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &crt->pk ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 845 {
kadonotakashi 0:8fdf9a60065b 846 mbedtls_x509_crt_free( crt );
kadonotakashi 0:8fdf9a60065b 847 return( ret );
kadonotakashi 0:8fdf9a60065b 848 }
kadonotakashi 0:8fdf9a60065b 849
kadonotakashi 0:8fdf9a60065b 850 /*
kadonotakashi 0:8fdf9a60065b 851 * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
kadonotakashi 0:8fdf9a60065b 852 * -- If present, version shall be v2 or v3
kadonotakashi 0:8fdf9a60065b 853 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
kadonotakashi 0:8fdf9a60065b 854 * -- If present, version shall be v2 or v3
kadonotakashi 0:8fdf9a60065b 855 * extensions [3] EXPLICIT Extensions OPTIONAL
kadonotakashi 0:8fdf9a60065b 856 * -- If present, version shall be v3
kadonotakashi 0:8fdf9a60065b 857 */
kadonotakashi 0:8fdf9a60065b 858 if( crt->version == 2 || crt->version == 3 )
kadonotakashi 0:8fdf9a60065b 859 {
kadonotakashi 0:8fdf9a60065b 860 ret = x509_get_uid( &p, end, &crt->issuer_id, 1 );
kadonotakashi 0:8fdf9a60065b 861 if( ret != 0 )
kadonotakashi 0:8fdf9a60065b 862 {
kadonotakashi 0:8fdf9a60065b 863 mbedtls_x509_crt_free( crt );
kadonotakashi 0:8fdf9a60065b 864 return( ret );
kadonotakashi 0:8fdf9a60065b 865 }
kadonotakashi 0:8fdf9a60065b 866 }
kadonotakashi 0:8fdf9a60065b 867
kadonotakashi 0:8fdf9a60065b 868 if( crt->version == 2 || crt->version == 3 )
kadonotakashi 0:8fdf9a60065b 869 {
kadonotakashi 0:8fdf9a60065b 870 ret = x509_get_uid( &p, end, &crt->subject_id, 2 );
kadonotakashi 0:8fdf9a60065b 871 if( ret != 0 )
kadonotakashi 0:8fdf9a60065b 872 {
kadonotakashi 0:8fdf9a60065b 873 mbedtls_x509_crt_free( crt );
kadonotakashi 0:8fdf9a60065b 874 return( ret );
kadonotakashi 0:8fdf9a60065b 875 }
kadonotakashi 0:8fdf9a60065b 876 }
kadonotakashi 0:8fdf9a60065b 877
kadonotakashi 0:8fdf9a60065b 878 #if !defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3)
kadonotakashi 0:8fdf9a60065b 879 if( crt->version == 3 )
kadonotakashi 0:8fdf9a60065b 880 #endif
kadonotakashi 0:8fdf9a60065b 881 {
kadonotakashi 0:8fdf9a60065b 882 ret = x509_get_crt_ext( &p, end, crt );
kadonotakashi 0:8fdf9a60065b 883 if( ret != 0 )
kadonotakashi 0:8fdf9a60065b 884 {
kadonotakashi 0:8fdf9a60065b 885 mbedtls_x509_crt_free( crt );
kadonotakashi 0:8fdf9a60065b 886 return( ret );
kadonotakashi 0:8fdf9a60065b 887 }
kadonotakashi 0:8fdf9a60065b 888 }
kadonotakashi 0:8fdf9a60065b 889
kadonotakashi 0:8fdf9a60065b 890 if( p != end )
kadonotakashi 0:8fdf9a60065b 891 {
kadonotakashi 0:8fdf9a60065b 892 mbedtls_x509_crt_free( crt );
kadonotakashi 0:8fdf9a60065b 893 return( MBEDTLS_ERR_X509_INVALID_FORMAT +
kadonotakashi 0:8fdf9a60065b 894 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kadonotakashi 0:8fdf9a60065b 895 }
kadonotakashi 0:8fdf9a60065b 896
kadonotakashi 0:8fdf9a60065b 897 end = crt_end;
kadonotakashi 0:8fdf9a60065b 898
kadonotakashi 0:8fdf9a60065b 899 /*
kadonotakashi 0:8fdf9a60065b 900 * }
kadonotakashi 0:8fdf9a60065b 901 * -- end of TBSCertificate
kadonotakashi 0:8fdf9a60065b 902 *
kadonotakashi 0:8fdf9a60065b 903 * signatureAlgorithm AlgorithmIdentifier,
kadonotakashi 0:8fdf9a60065b 904 * signatureValue BIT STRING
kadonotakashi 0:8fdf9a60065b 905 */
kadonotakashi 0:8fdf9a60065b 906 if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 907 {
kadonotakashi 0:8fdf9a60065b 908 mbedtls_x509_crt_free( crt );
kadonotakashi 0:8fdf9a60065b 909 return( ret );
kadonotakashi 0:8fdf9a60065b 910 }
kadonotakashi 0:8fdf9a60065b 911
kadonotakashi 0:8fdf9a60065b 912 if( crt->sig_oid.len != sig_oid2.len ||
kadonotakashi 0:8fdf9a60065b 913 memcmp( crt->sig_oid.p, sig_oid2.p, crt->sig_oid.len ) != 0 ||
kadonotakashi 0:8fdf9a60065b 914 sig_params1.len != sig_params2.len ||
kadonotakashi 0:8fdf9a60065b 915 ( sig_params1.len != 0 &&
kadonotakashi 0:8fdf9a60065b 916 memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) )
kadonotakashi 0:8fdf9a60065b 917 {
kadonotakashi 0:8fdf9a60065b 918 mbedtls_x509_crt_free( crt );
kadonotakashi 0:8fdf9a60065b 919 return( MBEDTLS_ERR_X509_SIG_MISMATCH );
kadonotakashi 0:8fdf9a60065b 920 }
kadonotakashi 0:8fdf9a60065b 921
kadonotakashi 0:8fdf9a60065b 922 if( ( ret = mbedtls_x509_get_sig( &p, end, &crt->sig ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 923 {
kadonotakashi 0:8fdf9a60065b 924 mbedtls_x509_crt_free( crt );
kadonotakashi 0:8fdf9a60065b 925 return( ret );
kadonotakashi 0:8fdf9a60065b 926 }
kadonotakashi 0:8fdf9a60065b 927
kadonotakashi 0:8fdf9a60065b 928 if( p != end )
kadonotakashi 0:8fdf9a60065b 929 {
kadonotakashi 0:8fdf9a60065b 930 mbedtls_x509_crt_free( crt );
kadonotakashi 0:8fdf9a60065b 931 return( MBEDTLS_ERR_X509_INVALID_FORMAT +
kadonotakashi 0:8fdf9a60065b 932 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kadonotakashi 0:8fdf9a60065b 933 }
kadonotakashi 0:8fdf9a60065b 934
kadonotakashi 0:8fdf9a60065b 935 return( 0 );
kadonotakashi 0:8fdf9a60065b 936 }
kadonotakashi 0:8fdf9a60065b 937
kadonotakashi 0:8fdf9a60065b 938 /*
kadonotakashi 0:8fdf9a60065b 939 * Parse one X.509 certificate in DER format from a buffer and add them to a
kadonotakashi 0:8fdf9a60065b 940 * chained list
kadonotakashi 0:8fdf9a60065b 941 */
kadonotakashi 0:8fdf9a60065b 942 int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *buf,
kadonotakashi 0:8fdf9a60065b 943 size_t buflen )
kadonotakashi 0:8fdf9a60065b 944 {
kadonotakashi 0:8fdf9a60065b 945 int ret;
kadonotakashi 0:8fdf9a60065b 946 mbedtls_x509_crt *crt = chain, *prev = NULL;
kadonotakashi 0:8fdf9a60065b 947
kadonotakashi 0:8fdf9a60065b 948 /*
kadonotakashi 0:8fdf9a60065b 949 * Check for valid input
kadonotakashi 0:8fdf9a60065b 950 */
kadonotakashi 0:8fdf9a60065b 951 if( crt == NULL || buf == NULL )
kadonotakashi 0:8fdf9a60065b 952 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
kadonotakashi 0:8fdf9a60065b 953
kadonotakashi 0:8fdf9a60065b 954 while( crt->version != 0 && crt->next != NULL )
kadonotakashi 0:8fdf9a60065b 955 {
kadonotakashi 0:8fdf9a60065b 956 prev = crt;
kadonotakashi 0:8fdf9a60065b 957 crt = crt->next;
kadonotakashi 0:8fdf9a60065b 958 }
kadonotakashi 0:8fdf9a60065b 959
kadonotakashi 0:8fdf9a60065b 960 /*
kadonotakashi 0:8fdf9a60065b 961 * Add new certificate on the end of the chain if needed.
kadonotakashi 0:8fdf9a60065b 962 */
kadonotakashi 0:8fdf9a60065b 963 if( crt->version != 0 && crt->next == NULL )
kadonotakashi 0:8fdf9a60065b 964 {
kadonotakashi 0:8fdf9a60065b 965 crt->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) );
kadonotakashi 0:8fdf9a60065b 966
kadonotakashi 0:8fdf9a60065b 967 if( crt->next == NULL )
kadonotakashi 0:8fdf9a60065b 968 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
kadonotakashi 0:8fdf9a60065b 969
kadonotakashi 0:8fdf9a60065b 970 prev = crt;
kadonotakashi 0:8fdf9a60065b 971 mbedtls_x509_crt_init( crt->next );
kadonotakashi 0:8fdf9a60065b 972 crt = crt->next;
kadonotakashi 0:8fdf9a60065b 973 }
kadonotakashi 0:8fdf9a60065b 974
kadonotakashi 0:8fdf9a60065b 975 if( ( ret = x509_crt_parse_der_core( crt, buf, buflen ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 976 {
kadonotakashi 0:8fdf9a60065b 977 if( prev )
kadonotakashi 0:8fdf9a60065b 978 prev->next = NULL;
kadonotakashi 0:8fdf9a60065b 979
kadonotakashi 0:8fdf9a60065b 980 if( crt != chain )
kadonotakashi 0:8fdf9a60065b 981 mbedtls_free( crt );
kadonotakashi 0:8fdf9a60065b 982
kadonotakashi 0:8fdf9a60065b 983 return( ret );
kadonotakashi 0:8fdf9a60065b 984 }
kadonotakashi 0:8fdf9a60065b 985
kadonotakashi 0:8fdf9a60065b 986 return( 0 );
kadonotakashi 0:8fdf9a60065b 987 }
kadonotakashi 0:8fdf9a60065b 988
kadonotakashi 0:8fdf9a60065b 989 /*
kadonotakashi 0:8fdf9a60065b 990 * Parse one or more PEM certificates from a buffer and add them to the chained
kadonotakashi 0:8fdf9a60065b 991 * list
kadonotakashi 0:8fdf9a60065b 992 */
kadonotakashi 0:8fdf9a60065b 993 int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen )
kadonotakashi 0:8fdf9a60065b 994 {
kadonotakashi 0:8fdf9a60065b 995 #if defined(MBEDTLS_PEM_PARSE_C)
kadonotakashi 0:8fdf9a60065b 996 int success = 0, first_error = 0, total_failed = 0;
kadonotakashi 0:8fdf9a60065b 997 int buf_format = MBEDTLS_X509_FORMAT_DER;
kadonotakashi 0:8fdf9a60065b 998 #endif
kadonotakashi 0:8fdf9a60065b 999
kadonotakashi 0:8fdf9a60065b 1000 /*
kadonotakashi 0:8fdf9a60065b 1001 * Check for valid input
kadonotakashi 0:8fdf9a60065b 1002 */
kadonotakashi 0:8fdf9a60065b 1003 if( chain == NULL || buf == NULL )
kadonotakashi 0:8fdf9a60065b 1004 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
kadonotakashi 0:8fdf9a60065b 1005
kadonotakashi 0:8fdf9a60065b 1006 /*
kadonotakashi 0:8fdf9a60065b 1007 * Determine buffer content. Buffer contains either one DER certificate or
kadonotakashi 0:8fdf9a60065b 1008 * one or more PEM certificates.
kadonotakashi 0:8fdf9a60065b 1009 */
kadonotakashi 0:8fdf9a60065b 1010 #if defined(MBEDTLS_PEM_PARSE_C)
kadonotakashi 0:8fdf9a60065b 1011 if( buflen != 0 && buf[buflen - 1] == '\0' &&
kadonotakashi 0:8fdf9a60065b 1012 strstr( (const char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL )
kadonotakashi 0:8fdf9a60065b 1013 {
kadonotakashi 0:8fdf9a60065b 1014 buf_format = MBEDTLS_X509_FORMAT_PEM;
kadonotakashi 0:8fdf9a60065b 1015 }
kadonotakashi 0:8fdf9a60065b 1016
kadonotakashi 0:8fdf9a60065b 1017 if( buf_format == MBEDTLS_X509_FORMAT_DER )
kadonotakashi 0:8fdf9a60065b 1018 return mbedtls_x509_crt_parse_der( chain, buf, buflen );
kadonotakashi 0:8fdf9a60065b 1019 #else
kadonotakashi 0:8fdf9a60065b 1020 return mbedtls_x509_crt_parse_der( chain, buf, buflen );
kadonotakashi 0:8fdf9a60065b 1021 #endif
kadonotakashi 0:8fdf9a60065b 1022
kadonotakashi 0:8fdf9a60065b 1023 #if defined(MBEDTLS_PEM_PARSE_C)
kadonotakashi 0:8fdf9a60065b 1024 if( buf_format == MBEDTLS_X509_FORMAT_PEM )
kadonotakashi 0:8fdf9a60065b 1025 {
kadonotakashi 0:8fdf9a60065b 1026 int ret;
kadonotakashi 0:8fdf9a60065b 1027 mbedtls_pem_context pem;
kadonotakashi 0:8fdf9a60065b 1028
kadonotakashi 0:8fdf9a60065b 1029 /* 1 rather than 0 since the terminating NULL byte is counted in */
kadonotakashi 0:8fdf9a60065b 1030 while( buflen > 1 )
kadonotakashi 0:8fdf9a60065b 1031 {
kadonotakashi 0:8fdf9a60065b 1032 size_t use_len;
kadonotakashi 0:8fdf9a60065b 1033 mbedtls_pem_init( &pem );
kadonotakashi 0:8fdf9a60065b 1034
kadonotakashi 0:8fdf9a60065b 1035 /* If we get there, we know the string is null-terminated */
kadonotakashi 0:8fdf9a60065b 1036 ret = mbedtls_pem_read_buffer( &pem,
kadonotakashi 0:8fdf9a60065b 1037 "-----BEGIN CERTIFICATE-----",
kadonotakashi 0:8fdf9a60065b 1038 "-----END CERTIFICATE-----",
kadonotakashi 0:8fdf9a60065b 1039 buf, NULL, 0, &use_len );
kadonotakashi 0:8fdf9a60065b 1040
kadonotakashi 0:8fdf9a60065b 1041 if( ret == 0 )
kadonotakashi 0:8fdf9a60065b 1042 {
kadonotakashi 0:8fdf9a60065b 1043 /*
kadonotakashi 0:8fdf9a60065b 1044 * Was PEM encoded
kadonotakashi 0:8fdf9a60065b 1045 */
kadonotakashi 0:8fdf9a60065b 1046 buflen -= use_len;
kadonotakashi 0:8fdf9a60065b 1047 buf += use_len;
kadonotakashi 0:8fdf9a60065b 1048 }
kadonotakashi 0:8fdf9a60065b 1049 else if( ret == MBEDTLS_ERR_PEM_BAD_INPUT_DATA )
kadonotakashi 0:8fdf9a60065b 1050 {
kadonotakashi 0:8fdf9a60065b 1051 return( ret );
kadonotakashi 0:8fdf9a60065b 1052 }
kadonotakashi 0:8fdf9a60065b 1053 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
kadonotakashi 0:8fdf9a60065b 1054 {
kadonotakashi 0:8fdf9a60065b 1055 mbedtls_pem_free( &pem );
kadonotakashi 0:8fdf9a60065b 1056
kadonotakashi 0:8fdf9a60065b 1057 /*
kadonotakashi 0:8fdf9a60065b 1058 * PEM header and footer were found
kadonotakashi 0:8fdf9a60065b 1059 */
kadonotakashi 0:8fdf9a60065b 1060 buflen -= use_len;
kadonotakashi 0:8fdf9a60065b 1061 buf += use_len;
kadonotakashi 0:8fdf9a60065b 1062
kadonotakashi 0:8fdf9a60065b 1063 if( first_error == 0 )
kadonotakashi 0:8fdf9a60065b 1064 first_error = ret;
kadonotakashi 0:8fdf9a60065b 1065
kadonotakashi 0:8fdf9a60065b 1066 total_failed++;
kadonotakashi 0:8fdf9a60065b 1067 continue;
kadonotakashi 0:8fdf9a60065b 1068 }
kadonotakashi 0:8fdf9a60065b 1069 else
kadonotakashi 0:8fdf9a60065b 1070 break;
kadonotakashi 0:8fdf9a60065b 1071
kadonotakashi 0:8fdf9a60065b 1072 ret = mbedtls_x509_crt_parse_der( chain, pem.buf, pem.buflen );
kadonotakashi 0:8fdf9a60065b 1073
kadonotakashi 0:8fdf9a60065b 1074 mbedtls_pem_free( &pem );
kadonotakashi 0:8fdf9a60065b 1075
kadonotakashi 0:8fdf9a60065b 1076 if( ret != 0 )
kadonotakashi 0:8fdf9a60065b 1077 {
kadonotakashi 0:8fdf9a60065b 1078 /*
kadonotakashi 0:8fdf9a60065b 1079 * Quit parsing on a memory error
kadonotakashi 0:8fdf9a60065b 1080 */
kadonotakashi 0:8fdf9a60065b 1081 if( ret == MBEDTLS_ERR_X509_ALLOC_FAILED )
kadonotakashi 0:8fdf9a60065b 1082 return( ret );
kadonotakashi 0:8fdf9a60065b 1083
kadonotakashi 0:8fdf9a60065b 1084 if( first_error == 0 )
kadonotakashi 0:8fdf9a60065b 1085 first_error = ret;
kadonotakashi 0:8fdf9a60065b 1086
kadonotakashi 0:8fdf9a60065b 1087 total_failed++;
kadonotakashi 0:8fdf9a60065b 1088 continue;
kadonotakashi 0:8fdf9a60065b 1089 }
kadonotakashi 0:8fdf9a60065b 1090
kadonotakashi 0:8fdf9a60065b 1091 success = 1;
kadonotakashi 0:8fdf9a60065b 1092 }
kadonotakashi 0:8fdf9a60065b 1093 }
kadonotakashi 0:8fdf9a60065b 1094
kadonotakashi 0:8fdf9a60065b 1095 if( success )
kadonotakashi 0:8fdf9a60065b 1096 return( total_failed );
kadonotakashi 0:8fdf9a60065b 1097 else if( first_error )
kadonotakashi 0:8fdf9a60065b 1098 return( first_error );
kadonotakashi 0:8fdf9a60065b 1099 else
kadonotakashi 0:8fdf9a60065b 1100 return( MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT );
kadonotakashi 0:8fdf9a60065b 1101 #endif /* MBEDTLS_PEM_PARSE_C */
kadonotakashi 0:8fdf9a60065b 1102 }
kadonotakashi 0:8fdf9a60065b 1103
kadonotakashi 0:8fdf9a60065b 1104 #if defined(MBEDTLS_FS_IO)
kadonotakashi 0:8fdf9a60065b 1105 /*
kadonotakashi 0:8fdf9a60065b 1106 * Load one or more certificates and add them to the chained list
kadonotakashi 0:8fdf9a60065b 1107 */
kadonotakashi 0:8fdf9a60065b 1108 int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path )
kadonotakashi 0:8fdf9a60065b 1109 {
kadonotakashi 0:8fdf9a60065b 1110 int ret;
kadonotakashi 0:8fdf9a60065b 1111 size_t n;
kadonotakashi 0:8fdf9a60065b 1112 unsigned char *buf;
kadonotakashi 0:8fdf9a60065b 1113
kadonotakashi 0:8fdf9a60065b 1114 if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 1115 return( ret );
kadonotakashi 0:8fdf9a60065b 1116
kadonotakashi 0:8fdf9a60065b 1117 ret = mbedtls_x509_crt_parse( chain, buf, n );
kadonotakashi 0:8fdf9a60065b 1118
kadonotakashi 0:8fdf9a60065b 1119 mbedtls_platform_zeroize( buf, n );
kadonotakashi 0:8fdf9a60065b 1120 mbedtls_free( buf );
kadonotakashi 0:8fdf9a60065b 1121
kadonotakashi 0:8fdf9a60065b 1122 return( ret );
kadonotakashi 0:8fdf9a60065b 1123 }
kadonotakashi 0:8fdf9a60065b 1124
kadonotakashi 0:8fdf9a60065b 1125 int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
kadonotakashi 0:8fdf9a60065b 1126 {
kadonotakashi 0:8fdf9a60065b 1127 int ret = 0;
kadonotakashi 0:8fdf9a60065b 1128 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
kadonotakashi 0:8fdf9a60065b 1129 int w_ret;
kadonotakashi 0:8fdf9a60065b 1130 WCHAR szDir[MAX_PATH];
kadonotakashi 0:8fdf9a60065b 1131 char filename[MAX_PATH];
kadonotakashi 0:8fdf9a60065b 1132 char *p;
kadonotakashi 0:8fdf9a60065b 1133 size_t len = strlen( path );
kadonotakashi 0:8fdf9a60065b 1134
kadonotakashi 0:8fdf9a60065b 1135 WIN32_FIND_DATAW file_data;
kadonotakashi 0:8fdf9a60065b 1136 HANDLE hFind;
kadonotakashi 0:8fdf9a60065b 1137
kadonotakashi 0:8fdf9a60065b 1138 if( len > MAX_PATH - 3 )
kadonotakashi 0:8fdf9a60065b 1139 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
kadonotakashi 0:8fdf9a60065b 1140
kadonotakashi 0:8fdf9a60065b 1141 memset( szDir, 0, sizeof(szDir) );
kadonotakashi 0:8fdf9a60065b 1142 memset( filename, 0, MAX_PATH );
kadonotakashi 0:8fdf9a60065b 1143 memcpy( filename, path, len );
kadonotakashi 0:8fdf9a60065b 1144 filename[len++] = '\\';
kadonotakashi 0:8fdf9a60065b 1145 p = filename + len;
kadonotakashi 0:8fdf9a60065b 1146 filename[len++] = '*';
kadonotakashi 0:8fdf9a60065b 1147
kadonotakashi 0:8fdf9a60065b 1148 w_ret = MultiByteToWideChar( CP_ACP, 0, filename, (int)len, szDir,
kadonotakashi 0:8fdf9a60065b 1149 MAX_PATH - 3 );
kadonotakashi 0:8fdf9a60065b 1150 if( w_ret == 0 )
kadonotakashi 0:8fdf9a60065b 1151 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
kadonotakashi 0:8fdf9a60065b 1152
kadonotakashi 0:8fdf9a60065b 1153 hFind = FindFirstFileW( szDir, &file_data );
kadonotakashi 0:8fdf9a60065b 1154 if( hFind == INVALID_HANDLE_VALUE )
kadonotakashi 0:8fdf9a60065b 1155 return( MBEDTLS_ERR_X509_FILE_IO_ERROR );
kadonotakashi 0:8fdf9a60065b 1156
kadonotakashi 0:8fdf9a60065b 1157 len = MAX_PATH - len;
kadonotakashi 0:8fdf9a60065b 1158 do
kadonotakashi 0:8fdf9a60065b 1159 {
kadonotakashi 0:8fdf9a60065b 1160 memset( p, 0, len );
kadonotakashi 0:8fdf9a60065b 1161
kadonotakashi 0:8fdf9a60065b 1162 if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
kadonotakashi 0:8fdf9a60065b 1163 continue;
kadonotakashi 0:8fdf9a60065b 1164
kadonotakashi 0:8fdf9a60065b 1165 w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName,
kadonotakashi 0:8fdf9a60065b 1166 lstrlenW( file_data.cFileName ),
kadonotakashi 0:8fdf9a60065b 1167 p, (int) len - 1,
kadonotakashi 0:8fdf9a60065b 1168 NULL, NULL );
kadonotakashi 0:8fdf9a60065b 1169 if( w_ret == 0 )
kadonotakashi 0:8fdf9a60065b 1170 {
kadonotakashi 0:8fdf9a60065b 1171 ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
kadonotakashi 0:8fdf9a60065b 1172 goto cleanup;
kadonotakashi 0:8fdf9a60065b 1173 }
kadonotakashi 0:8fdf9a60065b 1174
kadonotakashi 0:8fdf9a60065b 1175 w_ret = mbedtls_x509_crt_parse_file( chain, filename );
kadonotakashi 0:8fdf9a60065b 1176 if( w_ret < 0 )
kadonotakashi 0:8fdf9a60065b 1177 ret++;
kadonotakashi 0:8fdf9a60065b 1178 else
kadonotakashi 0:8fdf9a60065b 1179 ret += w_ret;
kadonotakashi 0:8fdf9a60065b 1180 }
kadonotakashi 0:8fdf9a60065b 1181 while( FindNextFileW( hFind, &file_data ) != 0 );
kadonotakashi 0:8fdf9a60065b 1182
kadonotakashi 0:8fdf9a60065b 1183 if( GetLastError() != ERROR_NO_MORE_FILES )
kadonotakashi 0:8fdf9a60065b 1184 ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
kadonotakashi 0:8fdf9a60065b 1185
kadonotakashi 0:8fdf9a60065b 1186 cleanup:
kadonotakashi 0:8fdf9a60065b 1187 FindClose( hFind );
kadonotakashi 0:8fdf9a60065b 1188 #else /* _WIN32 */
kadonotakashi 0:8fdf9a60065b 1189 int t_ret;
kadonotakashi 0:8fdf9a60065b 1190 int snp_ret;
kadonotakashi 0:8fdf9a60065b 1191 struct stat sb;
kadonotakashi 0:8fdf9a60065b 1192 struct dirent *entry;
kadonotakashi 0:8fdf9a60065b 1193 char entry_name[MBEDTLS_X509_MAX_FILE_PATH_LEN];
kadonotakashi 0:8fdf9a60065b 1194 DIR *dir = opendir( path );
kadonotakashi 0:8fdf9a60065b 1195
kadonotakashi 0:8fdf9a60065b 1196 if( dir == NULL )
kadonotakashi 0:8fdf9a60065b 1197 return( MBEDTLS_ERR_X509_FILE_IO_ERROR );
kadonotakashi 0:8fdf9a60065b 1198
kadonotakashi 0:8fdf9a60065b 1199 #if defined(MBEDTLS_THREADING_C)
kadonotakashi 0:8fdf9a60065b 1200 if( ( ret = mbedtls_mutex_lock( &mbedtls_threading_readdir_mutex ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 1201 {
kadonotakashi 0:8fdf9a60065b 1202 closedir( dir );
kadonotakashi 0:8fdf9a60065b 1203 return( ret );
kadonotakashi 0:8fdf9a60065b 1204 }
kadonotakashi 0:8fdf9a60065b 1205 #endif /* MBEDTLS_THREADING_C */
kadonotakashi 0:8fdf9a60065b 1206
kadonotakashi 0:8fdf9a60065b 1207 while( ( entry = readdir( dir ) ) != NULL )
kadonotakashi 0:8fdf9a60065b 1208 {
kadonotakashi 0:8fdf9a60065b 1209 snp_ret = mbedtls_snprintf( entry_name, sizeof entry_name,
kadonotakashi 0:8fdf9a60065b 1210 "%s/%s", path, entry->d_name );
kadonotakashi 0:8fdf9a60065b 1211
kadonotakashi 0:8fdf9a60065b 1212 if( snp_ret < 0 || (size_t)snp_ret >= sizeof entry_name )
kadonotakashi 0:8fdf9a60065b 1213 {
kadonotakashi 0:8fdf9a60065b 1214 ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
kadonotakashi 0:8fdf9a60065b 1215 goto cleanup;
kadonotakashi 0:8fdf9a60065b 1216 }
kadonotakashi 0:8fdf9a60065b 1217 else if( stat( entry_name, &sb ) == -1 )
kadonotakashi 0:8fdf9a60065b 1218 {
kadonotakashi 0:8fdf9a60065b 1219 ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
kadonotakashi 0:8fdf9a60065b 1220 goto cleanup;
kadonotakashi 0:8fdf9a60065b 1221 }
kadonotakashi 0:8fdf9a60065b 1222
kadonotakashi 0:8fdf9a60065b 1223 if( !S_ISREG( sb.st_mode ) )
kadonotakashi 0:8fdf9a60065b 1224 continue;
kadonotakashi 0:8fdf9a60065b 1225
kadonotakashi 0:8fdf9a60065b 1226 // Ignore parse errors
kadonotakashi 0:8fdf9a60065b 1227 //
kadonotakashi 0:8fdf9a60065b 1228 t_ret = mbedtls_x509_crt_parse_file( chain, entry_name );
kadonotakashi 0:8fdf9a60065b 1229 if( t_ret < 0 )
kadonotakashi 0:8fdf9a60065b 1230 ret++;
kadonotakashi 0:8fdf9a60065b 1231 else
kadonotakashi 0:8fdf9a60065b 1232 ret += t_ret;
kadonotakashi 0:8fdf9a60065b 1233 }
kadonotakashi 0:8fdf9a60065b 1234
kadonotakashi 0:8fdf9a60065b 1235 cleanup:
kadonotakashi 0:8fdf9a60065b 1236 closedir( dir );
kadonotakashi 0:8fdf9a60065b 1237
kadonotakashi 0:8fdf9a60065b 1238 #if defined(MBEDTLS_THREADING_C)
kadonotakashi 0:8fdf9a60065b 1239 if( mbedtls_mutex_unlock( &mbedtls_threading_readdir_mutex ) != 0 )
kadonotakashi 0:8fdf9a60065b 1240 ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR;
kadonotakashi 0:8fdf9a60065b 1241 #endif /* MBEDTLS_THREADING_C */
kadonotakashi 0:8fdf9a60065b 1242
kadonotakashi 0:8fdf9a60065b 1243 #endif /* _WIN32 */
kadonotakashi 0:8fdf9a60065b 1244
kadonotakashi 0:8fdf9a60065b 1245 return( ret );
kadonotakashi 0:8fdf9a60065b 1246 }
kadonotakashi 0:8fdf9a60065b 1247 #endif /* MBEDTLS_FS_IO */
kadonotakashi 0:8fdf9a60065b 1248
kadonotakashi 0:8fdf9a60065b 1249 static int x509_info_subject_alt_name( char **buf, size_t *size,
kadonotakashi 0:8fdf9a60065b 1250 const mbedtls_x509_sequence *subject_alt_name )
kadonotakashi 0:8fdf9a60065b 1251 {
kadonotakashi 0:8fdf9a60065b 1252 size_t i;
kadonotakashi 0:8fdf9a60065b 1253 size_t n = *size;
kadonotakashi 0:8fdf9a60065b 1254 char *p = *buf;
kadonotakashi 0:8fdf9a60065b 1255 const mbedtls_x509_sequence *cur = subject_alt_name;
kadonotakashi 0:8fdf9a60065b 1256 const char *sep = "";
kadonotakashi 0:8fdf9a60065b 1257 size_t sep_len = 0;
kadonotakashi 0:8fdf9a60065b 1258
kadonotakashi 0:8fdf9a60065b 1259 while( cur != NULL )
kadonotakashi 0:8fdf9a60065b 1260 {
kadonotakashi 0:8fdf9a60065b 1261 if( cur->buf.len + sep_len >= n )
kadonotakashi 0:8fdf9a60065b 1262 {
kadonotakashi 0:8fdf9a60065b 1263 *p = '\0';
kadonotakashi 0:8fdf9a60065b 1264 return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
kadonotakashi 0:8fdf9a60065b 1265 }
kadonotakashi 0:8fdf9a60065b 1266
kadonotakashi 0:8fdf9a60065b 1267 n -= cur->buf.len + sep_len;
kadonotakashi 0:8fdf9a60065b 1268 for( i = 0; i < sep_len; i++ )
kadonotakashi 0:8fdf9a60065b 1269 *p++ = sep[i];
kadonotakashi 0:8fdf9a60065b 1270 for( i = 0; i < cur->buf.len; i++ )
kadonotakashi 0:8fdf9a60065b 1271 *p++ = cur->buf.p[i];
kadonotakashi 0:8fdf9a60065b 1272
kadonotakashi 0:8fdf9a60065b 1273 sep = ", ";
kadonotakashi 0:8fdf9a60065b 1274 sep_len = 2;
kadonotakashi 0:8fdf9a60065b 1275
kadonotakashi 0:8fdf9a60065b 1276 cur = cur->next;
kadonotakashi 0:8fdf9a60065b 1277 }
kadonotakashi 0:8fdf9a60065b 1278
kadonotakashi 0:8fdf9a60065b 1279 *p = '\0';
kadonotakashi 0:8fdf9a60065b 1280
kadonotakashi 0:8fdf9a60065b 1281 *size = n;
kadonotakashi 0:8fdf9a60065b 1282 *buf = p;
kadonotakashi 0:8fdf9a60065b 1283
kadonotakashi 0:8fdf9a60065b 1284 return( 0 );
kadonotakashi 0:8fdf9a60065b 1285 }
kadonotakashi 0:8fdf9a60065b 1286
kadonotakashi 0:8fdf9a60065b 1287 #define PRINT_ITEM(i) \
kadonotakashi 0:8fdf9a60065b 1288 { \
kadonotakashi 0:8fdf9a60065b 1289 ret = mbedtls_snprintf( p, n, "%s" i, sep ); \
kadonotakashi 0:8fdf9a60065b 1290 MBEDTLS_X509_SAFE_SNPRINTF; \
kadonotakashi 0:8fdf9a60065b 1291 sep = ", "; \
kadonotakashi 0:8fdf9a60065b 1292 }
kadonotakashi 0:8fdf9a60065b 1293
kadonotakashi 0:8fdf9a60065b 1294 #define CERT_TYPE(type,name) \
kadonotakashi 0:8fdf9a60065b 1295 if( ns_cert_type & type ) \
kadonotakashi 0:8fdf9a60065b 1296 PRINT_ITEM( name );
kadonotakashi 0:8fdf9a60065b 1297
kadonotakashi 0:8fdf9a60065b 1298 static int x509_info_cert_type( char **buf, size_t *size,
kadonotakashi 0:8fdf9a60065b 1299 unsigned char ns_cert_type )
kadonotakashi 0:8fdf9a60065b 1300 {
kadonotakashi 0:8fdf9a60065b 1301 int ret;
kadonotakashi 0:8fdf9a60065b 1302 size_t n = *size;
kadonotakashi 0:8fdf9a60065b 1303 char *p = *buf;
kadonotakashi 0:8fdf9a60065b 1304 const char *sep = "";
kadonotakashi 0:8fdf9a60065b 1305
kadonotakashi 0:8fdf9a60065b 1306 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT, "SSL Client" );
kadonotakashi 0:8fdf9a60065b 1307 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER, "SSL Server" );
kadonotakashi 0:8fdf9a60065b 1308 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL, "Email" );
kadonotakashi 0:8fdf9a60065b 1309 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing" );
kadonotakashi 0:8fdf9a60065b 1310 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_RESERVED, "Reserved" );
kadonotakashi 0:8fdf9a60065b 1311 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CA, "SSL CA" );
kadonotakashi 0:8fdf9a60065b 1312 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA, "Email CA" );
kadonotakashi 0:8fdf9a60065b 1313 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA" );
kadonotakashi 0:8fdf9a60065b 1314
kadonotakashi 0:8fdf9a60065b 1315 *size = n;
kadonotakashi 0:8fdf9a60065b 1316 *buf = p;
kadonotakashi 0:8fdf9a60065b 1317
kadonotakashi 0:8fdf9a60065b 1318 return( 0 );
kadonotakashi 0:8fdf9a60065b 1319 }
kadonotakashi 0:8fdf9a60065b 1320
kadonotakashi 0:8fdf9a60065b 1321 #define KEY_USAGE(code,name) \
kadonotakashi 0:8fdf9a60065b 1322 if( key_usage & code ) \
kadonotakashi 0:8fdf9a60065b 1323 PRINT_ITEM( name );
kadonotakashi 0:8fdf9a60065b 1324
kadonotakashi 0:8fdf9a60065b 1325 static int x509_info_key_usage( char **buf, size_t *size,
kadonotakashi 0:8fdf9a60065b 1326 unsigned int key_usage )
kadonotakashi 0:8fdf9a60065b 1327 {
kadonotakashi 0:8fdf9a60065b 1328 int ret;
kadonotakashi 0:8fdf9a60065b 1329 size_t n = *size;
kadonotakashi 0:8fdf9a60065b 1330 char *p = *buf;
kadonotakashi 0:8fdf9a60065b 1331 const char *sep = "";
kadonotakashi 0:8fdf9a60065b 1332
kadonotakashi 0:8fdf9a60065b 1333 KEY_USAGE( MBEDTLS_X509_KU_DIGITAL_SIGNATURE, "Digital Signature" );
kadonotakashi 0:8fdf9a60065b 1334 KEY_USAGE( MBEDTLS_X509_KU_NON_REPUDIATION, "Non Repudiation" );
kadonotakashi 0:8fdf9a60065b 1335 KEY_USAGE( MBEDTLS_X509_KU_KEY_ENCIPHERMENT, "Key Encipherment" );
kadonotakashi 0:8fdf9a60065b 1336 KEY_USAGE( MBEDTLS_X509_KU_DATA_ENCIPHERMENT, "Data Encipherment" );
kadonotakashi 0:8fdf9a60065b 1337 KEY_USAGE( MBEDTLS_X509_KU_KEY_AGREEMENT, "Key Agreement" );
kadonotakashi 0:8fdf9a60065b 1338 KEY_USAGE( MBEDTLS_X509_KU_KEY_CERT_SIGN, "Key Cert Sign" );
kadonotakashi 0:8fdf9a60065b 1339 KEY_USAGE( MBEDTLS_X509_KU_CRL_SIGN, "CRL Sign" );
kadonotakashi 0:8fdf9a60065b 1340 KEY_USAGE( MBEDTLS_X509_KU_ENCIPHER_ONLY, "Encipher Only" );
kadonotakashi 0:8fdf9a60065b 1341 KEY_USAGE( MBEDTLS_X509_KU_DECIPHER_ONLY, "Decipher Only" );
kadonotakashi 0:8fdf9a60065b 1342
kadonotakashi 0:8fdf9a60065b 1343 *size = n;
kadonotakashi 0:8fdf9a60065b 1344 *buf = p;
kadonotakashi 0:8fdf9a60065b 1345
kadonotakashi 0:8fdf9a60065b 1346 return( 0 );
kadonotakashi 0:8fdf9a60065b 1347 }
kadonotakashi 0:8fdf9a60065b 1348
kadonotakashi 0:8fdf9a60065b 1349 static int x509_info_ext_key_usage( char **buf, size_t *size,
kadonotakashi 0:8fdf9a60065b 1350 const mbedtls_x509_sequence *extended_key_usage )
kadonotakashi 0:8fdf9a60065b 1351 {
kadonotakashi 0:8fdf9a60065b 1352 int ret;
kadonotakashi 0:8fdf9a60065b 1353 const char *desc;
kadonotakashi 0:8fdf9a60065b 1354 size_t n = *size;
kadonotakashi 0:8fdf9a60065b 1355 char *p = *buf;
kadonotakashi 0:8fdf9a60065b 1356 const mbedtls_x509_sequence *cur = extended_key_usage;
kadonotakashi 0:8fdf9a60065b 1357 const char *sep = "";
kadonotakashi 0:8fdf9a60065b 1358
kadonotakashi 0:8fdf9a60065b 1359 while( cur != NULL )
kadonotakashi 0:8fdf9a60065b 1360 {
kadonotakashi 0:8fdf9a60065b 1361 if( mbedtls_oid_get_extended_key_usage( &cur->buf, &desc ) != 0 )
kadonotakashi 0:8fdf9a60065b 1362 desc = "???";
kadonotakashi 0:8fdf9a60065b 1363
kadonotakashi 0:8fdf9a60065b 1364 ret = mbedtls_snprintf( p, n, "%s%s", sep, desc );
kadonotakashi 0:8fdf9a60065b 1365 MBEDTLS_X509_SAFE_SNPRINTF;
kadonotakashi 0:8fdf9a60065b 1366
kadonotakashi 0:8fdf9a60065b 1367 sep = ", ";
kadonotakashi 0:8fdf9a60065b 1368
kadonotakashi 0:8fdf9a60065b 1369 cur = cur->next;
kadonotakashi 0:8fdf9a60065b 1370 }
kadonotakashi 0:8fdf9a60065b 1371
kadonotakashi 0:8fdf9a60065b 1372 *size = n;
kadonotakashi 0:8fdf9a60065b 1373 *buf = p;
kadonotakashi 0:8fdf9a60065b 1374
kadonotakashi 0:8fdf9a60065b 1375 return( 0 );
kadonotakashi 0:8fdf9a60065b 1376 }
kadonotakashi 0:8fdf9a60065b 1377
kadonotakashi 0:8fdf9a60065b 1378 /*
kadonotakashi 0:8fdf9a60065b 1379 * Return an informational string about the certificate.
kadonotakashi 0:8fdf9a60065b 1380 */
kadonotakashi 0:8fdf9a60065b 1381 #define BEFORE_COLON 18
kadonotakashi 0:8fdf9a60065b 1382 #define BC "18"
kadonotakashi 0:8fdf9a60065b 1383 int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix,
kadonotakashi 0:8fdf9a60065b 1384 const mbedtls_x509_crt *crt )
kadonotakashi 0:8fdf9a60065b 1385 {
kadonotakashi 0:8fdf9a60065b 1386 int ret;
kadonotakashi 0:8fdf9a60065b 1387 size_t n;
kadonotakashi 0:8fdf9a60065b 1388 char *p;
kadonotakashi 0:8fdf9a60065b 1389 char key_size_str[BEFORE_COLON];
kadonotakashi 0:8fdf9a60065b 1390
kadonotakashi 0:8fdf9a60065b 1391 p = buf;
kadonotakashi 0:8fdf9a60065b 1392 n = size;
kadonotakashi 0:8fdf9a60065b 1393
kadonotakashi 0:8fdf9a60065b 1394 if( NULL == crt )
kadonotakashi 0:8fdf9a60065b 1395 {
kadonotakashi 0:8fdf9a60065b 1396 ret = mbedtls_snprintf( p, n, "\nCertificate is uninitialised!\n" );
kadonotakashi 0:8fdf9a60065b 1397 MBEDTLS_X509_SAFE_SNPRINTF;
kadonotakashi 0:8fdf9a60065b 1398
kadonotakashi 0:8fdf9a60065b 1399 return( (int) ( size - n ) );
kadonotakashi 0:8fdf9a60065b 1400 }
kadonotakashi 0:8fdf9a60065b 1401
kadonotakashi 0:8fdf9a60065b 1402 ret = mbedtls_snprintf( p, n, "%scert. version : %d\n",
kadonotakashi 0:8fdf9a60065b 1403 prefix, crt->version );
kadonotakashi 0:8fdf9a60065b 1404 MBEDTLS_X509_SAFE_SNPRINTF;
kadonotakashi 0:8fdf9a60065b 1405 ret = mbedtls_snprintf( p, n, "%sserial number : ",
kadonotakashi 0:8fdf9a60065b 1406 prefix );
kadonotakashi 0:8fdf9a60065b 1407 MBEDTLS_X509_SAFE_SNPRINTF;
kadonotakashi 0:8fdf9a60065b 1408
kadonotakashi 0:8fdf9a60065b 1409 ret = mbedtls_x509_serial_gets( p, n, &crt->serial );
kadonotakashi 0:8fdf9a60065b 1410 MBEDTLS_X509_SAFE_SNPRINTF;
kadonotakashi 0:8fdf9a60065b 1411
kadonotakashi 0:8fdf9a60065b 1412 ret = mbedtls_snprintf( p, n, "\n%sissuer name : ", prefix );
kadonotakashi 0:8fdf9a60065b 1413 MBEDTLS_X509_SAFE_SNPRINTF;
kadonotakashi 0:8fdf9a60065b 1414 ret = mbedtls_x509_dn_gets( p, n, &crt->issuer );
kadonotakashi 0:8fdf9a60065b 1415 MBEDTLS_X509_SAFE_SNPRINTF;
kadonotakashi 0:8fdf9a60065b 1416
kadonotakashi 0:8fdf9a60065b 1417 ret = mbedtls_snprintf( p, n, "\n%ssubject name : ", prefix );
kadonotakashi 0:8fdf9a60065b 1418 MBEDTLS_X509_SAFE_SNPRINTF;
kadonotakashi 0:8fdf9a60065b 1419 ret = mbedtls_x509_dn_gets( p, n, &crt->subject );
kadonotakashi 0:8fdf9a60065b 1420 MBEDTLS_X509_SAFE_SNPRINTF;
kadonotakashi 0:8fdf9a60065b 1421
kadonotakashi 0:8fdf9a60065b 1422 ret = mbedtls_snprintf( p, n, "\n%sissued on : " \
kadonotakashi 0:8fdf9a60065b 1423 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
kadonotakashi 0:8fdf9a60065b 1424 crt->valid_from.year, crt->valid_from.mon,
kadonotakashi 0:8fdf9a60065b 1425 crt->valid_from.day, crt->valid_from.hour,
kadonotakashi 0:8fdf9a60065b 1426 crt->valid_from.min, crt->valid_from.sec );
kadonotakashi 0:8fdf9a60065b 1427 MBEDTLS_X509_SAFE_SNPRINTF;
kadonotakashi 0:8fdf9a60065b 1428
kadonotakashi 0:8fdf9a60065b 1429 ret = mbedtls_snprintf( p, n, "\n%sexpires on : " \
kadonotakashi 0:8fdf9a60065b 1430 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
kadonotakashi 0:8fdf9a60065b 1431 crt->valid_to.year, crt->valid_to.mon,
kadonotakashi 0:8fdf9a60065b 1432 crt->valid_to.day, crt->valid_to.hour,
kadonotakashi 0:8fdf9a60065b 1433 crt->valid_to.min, crt->valid_to.sec );
kadonotakashi 0:8fdf9a60065b 1434 MBEDTLS_X509_SAFE_SNPRINTF;
kadonotakashi 0:8fdf9a60065b 1435
kadonotakashi 0:8fdf9a60065b 1436 ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix );
kadonotakashi 0:8fdf9a60065b 1437 MBEDTLS_X509_SAFE_SNPRINTF;
kadonotakashi 0:8fdf9a60065b 1438
kadonotakashi 0:8fdf9a60065b 1439 ret = mbedtls_x509_sig_alg_gets( p, n, &crt->sig_oid, crt->sig_pk,
kadonotakashi 0:8fdf9a60065b 1440 crt->sig_md, crt->sig_opts );
kadonotakashi 0:8fdf9a60065b 1441 MBEDTLS_X509_SAFE_SNPRINTF;
kadonotakashi 0:8fdf9a60065b 1442
kadonotakashi 0:8fdf9a60065b 1443 /* Key size */
kadonotakashi 0:8fdf9a60065b 1444 if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON,
kadonotakashi 0:8fdf9a60065b 1445 mbedtls_pk_get_name( &crt->pk ) ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 1446 {
kadonotakashi 0:8fdf9a60065b 1447 return( ret );
kadonotakashi 0:8fdf9a60065b 1448 }
kadonotakashi 0:8fdf9a60065b 1449
kadonotakashi 0:8fdf9a60065b 1450 ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str,
kadonotakashi 0:8fdf9a60065b 1451 (int) mbedtls_pk_get_bitlen( &crt->pk ) );
kadonotakashi 0:8fdf9a60065b 1452 MBEDTLS_X509_SAFE_SNPRINTF;
kadonotakashi 0:8fdf9a60065b 1453
kadonotakashi 0:8fdf9a60065b 1454 /*
kadonotakashi 0:8fdf9a60065b 1455 * Optional extensions
kadonotakashi 0:8fdf9a60065b 1456 */
kadonotakashi 0:8fdf9a60065b 1457
kadonotakashi 0:8fdf9a60065b 1458 if( crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS )
kadonotakashi 0:8fdf9a60065b 1459 {
kadonotakashi 0:8fdf9a60065b 1460 ret = mbedtls_snprintf( p, n, "\n%sbasic constraints : CA=%s", prefix,
kadonotakashi 0:8fdf9a60065b 1461 crt->ca_istrue ? "true" : "false" );
kadonotakashi 0:8fdf9a60065b 1462 MBEDTLS_X509_SAFE_SNPRINTF;
kadonotakashi 0:8fdf9a60065b 1463
kadonotakashi 0:8fdf9a60065b 1464 if( crt->max_pathlen > 0 )
kadonotakashi 0:8fdf9a60065b 1465 {
kadonotakashi 0:8fdf9a60065b 1466 ret = mbedtls_snprintf( p, n, ", max_pathlen=%d", crt->max_pathlen - 1 );
kadonotakashi 0:8fdf9a60065b 1467 MBEDTLS_X509_SAFE_SNPRINTF;
kadonotakashi 0:8fdf9a60065b 1468 }
kadonotakashi 0:8fdf9a60065b 1469 }
kadonotakashi 0:8fdf9a60065b 1470
kadonotakashi 0:8fdf9a60065b 1471 if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
kadonotakashi 0:8fdf9a60065b 1472 {
kadonotakashi 0:8fdf9a60065b 1473 ret = mbedtls_snprintf( p, n, "\n%ssubject alt name : ", prefix );
kadonotakashi 0:8fdf9a60065b 1474 MBEDTLS_X509_SAFE_SNPRINTF;
kadonotakashi 0:8fdf9a60065b 1475
kadonotakashi 0:8fdf9a60065b 1476 if( ( ret = x509_info_subject_alt_name( &p, &n,
kadonotakashi 0:8fdf9a60065b 1477 &crt->subject_alt_names ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 1478 return( ret );
kadonotakashi 0:8fdf9a60065b 1479 }
kadonotakashi 0:8fdf9a60065b 1480
kadonotakashi 0:8fdf9a60065b 1481 if( crt->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE )
kadonotakashi 0:8fdf9a60065b 1482 {
kadonotakashi 0:8fdf9a60065b 1483 ret = mbedtls_snprintf( p, n, "\n%scert. type : ", prefix );
kadonotakashi 0:8fdf9a60065b 1484 MBEDTLS_X509_SAFE_SNPRINTF;
kadonotakashi 0:8fdf9a60065b 1485
kadonotakashi 0:8fdf9a60065b 1486 if( ( ret = x509_info_cert_type( &p, &n, crt->ns_cert_type ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 1487 return( ret );
kadonotakashi 0:8fdf9a60065b 1488 }
kadonotakashi 0:8fdf9a60065b 1489
kadonotakashi 0:8fdf9a60065b 1490 if( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE )
kadonotakashi 0:8fdf9a60065b 1491 {
kadonotakashi 0:8fdf9a60065b 1492 ret = mbedtls_snprintf( p, n, "\n%skey usage : ", prefix );
kadonotakashi 0:8fdf9a60065b 1493 MBEDTLS_X509_SAFE_SNPRINTF;
kadonotakashi 0:8fdf9a60065b 1494
kadonotakashi 0:8fdf9a60065b 1495 if( ( ret = x509_info_key_usage( &p, &n, crt->key_usage ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 1496 return( ret );
kadonotakashi 0:8fdf9a60065b 1497 }
kadonotakashi 0:8fdf9a60065b 1498
kadonotakashi 0:8fdf9a60065b 1499 if( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE )
kadonotakashi 0:8fdf9a60065b 1500 {
kadonotakashi 0:8fdf9a60065b 1501 ret = mbedtls_snprintf( p, n, "\n%sext key usage : ", prefix );
kadonotakashi 0:8fdf9a60065b 1502 MBEDTLS_X509_SAFE_SNPRINTF;
kadonotakashi 0:8fdf9a60065b 1503
kadonotakashi 0:8fdf9a60065b 1504 if( ( ret = x509_info_ext_key_usage( &p, &n,
kadonotakashi 0:8fdf9a60065b 1505 &crt->ext_key_usage ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 1506 return( ret );
kadonotakashi 0:8fdf9a60065b 1507 }
kadonotakashi 0:8fdf9a60065b 1508
kadonotakashi 0:8fdf9a60065b 1509 ret = mbedtls_snprintf( p, n, "\n" );
kadonotakashi 0:8fdf9a60065b 1510 MBEDTLS_X509_SAFE_SNPRINTF;
kadonotakashi 0:8fdf9a60065b 1511
kadonotakashi 0:8fdf9a60065b 1512 return( (int) ( size - n ) );
kadonotakashi 0:8fdf9a60065b 1513 }
kadonotakashi 0:8fdf9a60065b 1514
kadonotakashi 0:8fdf9a60065b 1515 struct x509_crt_verify_string {
kadonotakashi 0:8fdf9a60065b 1516 int code;
kadonotakashi 0:8fdf9a60065b 1517 const char *string;
kadonotakashi 0:8fdf9a60065b 1518 };
kadonotakashi 0:8fdf9a60065b 1519
kadonotakashi 0:8fdf9a60065b 1520 static const struct x509_crt_verify_string x509_crt_verify_strings[] = {
kadonotakashi 0:8fdf9a60065b 1521 { MBEDTLS_X509_BADCERT_EXPIRED, "The certificate validity has expired" },
kadonotakashi 0:8fdf9a60065b 1522 { MBEDTLS_X509_BADCERT_REVOKED, "The certificate has been revoked (is on a CRL)" },
kadonotakashi 0:8fdf9a60065b 1523 { MBEDTLS_X509_BADCERT_CN_MISMATCH, "The certificate Common Name (CN) does not match with the expected CN" },
kadonotakashi 0:8fdf9a60065b 1524 { MBEDTLS_X509_BADCERT_NOT_TRUSTED, "The certificate is not correctly signed by the trusted CA" },
kadonotakashi 0:8fdf9a60065b 1525 { MBEDTLS_X509_BADCRL_NOT_TRUSTED, "The CRL is not correctly signed by the trusted CA" },
kadonotakashi 0:8fdf9a60065b 1526 { MBEDTLS_X509_BADCRL_EXPIRED, "The CRL is expired" },
kadonotakashi 0:8fdf9a60065b 1527 { MBEDTLS_X509_BADCERT_MISSING, "Certificate was missing" },
kadonotakashi 0:8fdf9a60065b 1528 { MBEDTLS_X509_BADCERT_SKIP_VERIFY, "Certificate verification was skipped" },
kadonotakashi 0:8fdf9a60065b 1529 { MBEDTLS_X509_BADCERT_OTHER, "Other reason (can be used by verify callback)" },
kadonotakashi 0:8fdf9a60065b 1530 { MBEDTLS_X509_BADCERT_FUTURE, "The certificate validity starts in the future" },
kadonotakashi 0:8fdf9a60065b 1531 { MBEDTLS_X509_BADCRL_FUTURE, "The CRL is from the future" },
kadonotakashi 0:8fdf9a60065b 1532 { MBEDTLS_X509_BADCERT_KEY_USAGE, "Usage does not match the keyUsage extension" },
kadonotakashi 0:8fdf9a60065b 1533 { MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, "Usage does not match the extendedKeyUsage extension" },
kadonotakashi 0:8fdf9a60065b 1534 { MBEDTLS_X509_BADCERT_NS_CERT_TYPE, "Usage does not match the nsCertType extension" },
kadonotakashi 0:8fdf9a60065b 1535 { MBEDTLS_X509_BADCERT_BAD_MD, "The certificate is signed with an unacceptable hash." },
kadonotakashi 0:8fdf9a60065b 1536 { MBEDTLS_X509_BADCERT_BAD_PK, "The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA)." },
kadonotakashi 0:8fdf9a60065b 1537 { MBEDTLS_X509_BADCERT_BAD_KEY, "The certificate is signed with an unacceptable key (eg bad curve, RSA too short)." },
kadonotakashi 0:8fdf9a60065b 1538 { MBEDTLS_X509_BADCRL_BAD_MD, "The CRL is signed with an unacceptable hash." },
kadonotakashi 0:8fdf9a60065b 1539 { MBEDTLS_X509_BADCRL_BAD_PK, "The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA)." },
kadonotakashi 0:8fdf9a60065b 1540 { MBEDTLS_X509_BADCRL_BAD_KEY, "The CRL is signed with an unacceptable key (eg bad curve, RSA too short)." },
kadonotakashi 0:8fdf9a60065b 1541 { 0, NULL }
kadonotakashi 0:8fdf9a60065b 1542 };
kadonotakashi 0:8fdf9a60065b 1543
kadonotakashi 0:8fdf9a60065b 1544 int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix,
kadonotakashi 0:8fdf9a60065b 1545 uint32_t flags )
kadonotakashi 0:8fdf9a60065b 1546 {
kadonotakashi 0:8fdf9a60065b 1547 int ret;
kadonotakashi 0:8fdf9a60065b 1548 const struct x509_crt_verify_string *cur;
kadonotakashi 0:8fdf9a60065b 1549 char *p = buf;
kadonotakashi 0:8fdf9a60065b 1550 size_t n = size;
kadonotakashi 0:8fdf9a60065b 1551
kadonotakashi 0:8fdf9a60065b 1552 for( cur = x509_crt_verify_strings; cur->string != NULL ; cur++ )
kadonotakashi 0:8fdf9a60065b 1553 {
kadonotakashi 0:8fdf9a60065b 1554 if( ( flags & cur->code ) == 0 )
kadonotakashi 0:8fdf9a60065b 1555 continue;
kadonotakashi 0:8fdf9a60065b 1556
kadonotakashi 0:8fdf9a60065b 1557 ret = mbedtls_snprintf( p, n, "%s%s\n", prefix, cur->string );
kadonotakashi 0:8fdf9a60065b 1558 MBEDTLS_X509_SAFE_SNPRINTF;
kadonotakashi 0:8fdf9a60065b 1559 flags ^= cur->code;
kadonotakashi 0:8fdf9a60065b 1560 }
kadonotakashi 0:8fdf9a60065b 1561
kadonotakashi 0:8fdf9a60065b 1562 if( flags != 0 )
kadonotakashi 0:8fdf9a60065b 1563 {
kadonotakashi 0:8fdf9a60065b 1564 ret = mbedtls_snprintf( p, n, "%sUnknown reason "
kadonotakashi 0:8fdf9a60065b 1565 "(this should not happen)\n", prefix );
kadonotakashi 0:8fdf9a60065b 1566 MBEDTLS_X509_SAFE_SNPRINTF;
kadonotakashi 0:8fdf9a60065b 1567 }
kadonotakashi 0:8fdf9a60065b 1568
kadonotakashi 0:8fdf9a60065b 1569 return( (int) ( size - n ) );
kadonotakashi 0:8fdf9a60065b 1570 }
kadonotakashi 0:8fdf9a60065b 1571
kadonotakashi 0:8fdf9a60065b 1572 #if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
kadonotakashi 0:8fdf9a60065b 1573 int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt,
kadonotakashi 0:8fdf9a60065b 1574 unsigned int usage )
kadonotakashi 0:8fdf9a60065b 1575 {
kadonotakashi 0:8fdf9a60065b 1576 unsigned int usage_must, usage_may;
kadonotakashi 0:8fdf9a60065b 1577 unsigned int may_mask = MBEDTLS_X509_KU_ENCIPHER_ONLY
kadonotakashi 0:8fdf9a60065b 1578 | MBEDTLS_X509_KU_DECIPHER_ONLY;
kadonotakashi 0:8fdf9a60065b 1579
kadonotakashi 0:8fdf9a60065b 1580 if( ( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) == 0 )
kadonotakashi 0:8fdf9a60065b 1581 return( 0 );
kadonotakashi 0:8fdf9a60065b 1582
kadonotakashi 0:8fdf9a60065b 1583 usage_must = usage & ~may_mask;
kadonotakashi 0:8fdf9a60065b 1584
kadonotakashi 0:8fdf9a60065b 1585 if( ( ( crt->key_usage & ~may_mask ) & usage_must ) != usage_must )
kadonotakashi 0:8fdf9a60065b 1586 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
kadonotakashi 0:8fdf9a60065b 1587
kadonotakashi 0:8fdf9a60065b 1588 usage_may = usage & may_mask;
kadonotakashi 0:8fdf9a60065b 1589
kadonotakashi 0:8fdf9a60065b 1590 if( ( ( crt->key_usage & may_mask ) | usage_may ) != usage_may )
kadonotakashi 0:8fdf9a60065b 1591 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
kadonotakashi 0:8fdf9a60065b 1592
kadonotakashi 0:8fdf9a60065b 1593 return( 0 );
kadonotakashi 0:8fdf9a60065b 1594 }
kadonotakashi 0:8fdf9a60065b 1595 #endif
kadonotakashi 0:8fdf9a60065b 1596
kadonotakashi 0:8fdf9a60065b 1597 #if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE)
kadonotakashi 0:8fdf9a60065b 1598 int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt,
kadonotakashi 0:8fdf9a60065b 1599 const char *usage_oid,
kadonotakashi 0:8fdf9a60065b 1600 size_t usage_len )
kadonotakashi 0:8fdf9a60065b 1601 {
kadonotakashi 0:8fdf9a60065b 1602 const mbedtls_x509_sequence *cur;
kadonotakashi 0:8fdf9a60065b 1603
kadonotakashi 0:8fdf9a60065b 1604 /* Extension is not mandatory, absent means no restriction */
kadonotakashi 0:8fdf9a60065b 1605 if( ( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) == 0 )
kadonotakashi 0:8fdf9a60065b 1606 return( 0 );
kadonotakashi 0:8fdf9a60065b 1607
kadonotakashi 0:8fdf9a60065b 1608 /*
kadonotakashi 0:8fdf9a60065b 1609 * Look for the requested usage (or wildcard ANY) in our list
kadonotakashi 0:8fdf9a60065b 1610 */
kadonotakashi 0:8fdf9a60065b 1611 for( cur = &crt->ext_key_usage; cur != NULL; cur = cur->next )
kadonotakashi 0:8fdf9a60065b 1612 {
kadonotakashi 0:8fdf9a60065b 1613 const mbedtls_x509_buf *cur_oid = &cur->buf;
kadonotakashi 0:8fdf9a60065b 1614
kadonotakashi 0:8fdf9a60065b 1615 if( cur_oid->len == usage_len &&
kadonotakashi 0:8fdf9a60065b 1616 memcmp( cur_oid->p, usage_oid, usage_len ) == 0 )
kadonotakashi 0:8fdf9a60065b 1617 {
kadonotakashi 0:8fdf9a60065b 1618 return( 0 );
kadonotakashi 0:8fdf9a60065b 1619 }
kadonotakashi 0:8fdf9a60065b 1620
kadonotakashi 0:8fdf9a60065b 1621 if( MBEDTLS_OID_CMP( MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE, cur_oid ) == 0 )
kadonotakashi 0:8fdf9a60065b 1622 return( 0 );
kadonotakashi 0:8fdf9a60065b 1623 }
kadonotakashi 0:8fdf9a60065b 1624
kadonotakashi 0:8fdf9a60065b 1625 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
kadonotakashi 0:8fdf9a60065b 1626 }
kadonotakashi 0:8fdf9a60065b 1627 #endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */
kadonotakashi 0:8fdf9a60065b 1628
kadonotakashi 0:8fdf9a60065b 1629 #if defined(MBEDTLS_X509_CRL_PARSE_C)
kadonotakashi 0:8fdf9a60065b 1630 /*
kadonotakashi 0:8fdf9a60065b 1631 * Return 1 if the certificate is revoked, or 0 otherwise.
kadonotakashi 0:8fdf9a60065b 1632 */
kadonotakashi 0:8fdf9a60065b 1633 int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl )
kadonotakashi 0:8fdf9a60065b 1634 {
kadonotakashi 0:8fdf9a60065b 1635 const mbedtls_x509_crl_entry *cur = &crl->entry;
kadonotakashi 0:8fdf9a60065b 1636
kadonotakashi 0:8fdf9a60065b 1637 while( cur != NULL && cur->serial.len != 0 )
kadonotakashi 0:8fdf9a60065b 1638 {
kadonotakashi 0:8fdf9a60065b 1639 if( crt->serial.len == cur->serial.len &&
kadonotakashi 0:8fdf9a60065b 1640 memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 )
kadonotakashi 0:8fdf9a60065b 1641 {
kadonotakashi 0:8fdf9a60065b 1642 if( mbedtls_x509_time_is_past( &cur->revocation_date ) )
kadonotakashi 0:8fdf9a60065b 1643 return( 1 );
kadonotakashi 0:8fdf9a60065b 1644 }
kadonotakashi 0:8fdf9a60065b 1645
kadonotakashi 0:8fdf9a60065b 1646 cur = cur->next;
kadonotakashi 0:8fdf9a60065b 1647 }
kadonotakashi 0:8fdf9a60065b 1648
kadonotakashi 0:8fdf9a60065b 1649 return( 0 );
kadonotakashi 0:8fdf9a60065b 1650 }
kadonotakashi 0:8fdf9a60065b 1651
kadonotakashi 0:8fdf9a60065b 1652 /*
kadonotakashi 0:8fdf9a60065b 1653 * Check that the given certificate is not revoked according to the CRL.
kadonotakashi 0:8fdf9a60065b 1654 * Skip validation if no CRL for the given CA is present.
kadonotakashi 0:8fdf9a60065b 1655 */
kadonotakashi 0:8fdf9a60065b 1656 static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca,
kadonotakashi 0:8fdf9a60065b 1657 mbedtls_x509_crl *crl_list,
kadonotakashi 0:8fdf9a60065b 1658 const mbedtls_x509_crt_profile *profile )
kadonotakashi 0:8fdf9a60065b 1659 {
kadonotakashi 0:8fdf9a60065b 1660 int flags = 0;
kadonotakashi 0:8fdf9a60065b 1661 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
kadonotakashi 0:8fdf9a60065b 1662 const mbedtls_md_info_t *md_info;
kadonotakashi 0:8fdf9a60065b 1663
kadonotakashi 0:8fdf9a60065b 1664 if( ca == NULL )
kadonotakashi 0:8fdf9a60065b 1665 return( flags );
kadonotakashi 0:8fdf9a60065b 1666
kadonotakashi 0:8fdf9a60065b 1667 while( crl_list != NULL )
kadonotakashi 0:8fdf9a60065b 1668 {
kadonotakashi 0:8fdf9a60065b 1669 if( crl_list->version == 0 ||
kadonotakashi 0:8fdf9a60065b 1670 crl_list->issuer_raw.len != ca->subject_raw.len ||
kadonotakashi 0:8fdf9a60065b 1671 memcmp( crl_list->issuer_raw.p, ca->subject_raw.p,
kadonotakashi 0:8fdf9a60065b 1672 crl_list->issuer_raw.len ) != 0 )
kadonotakashi 0:8fdf9a60065b 1673 {
kadonotakashi 0:8fdf9a60065b 1674 crl_list = crl_list->next;
kadonotakashi 0:8fdf9a60065b 1675 continue;
kadonotakashi 0:8fdf9a60065b 1676 }
kadonotakashi 0:8fdf9a60065b 1677
kadonotakashi 0:8fdf9a60065b 1678 /*
kadonotakashi 0:8fdf9a60065b 1679 * Check if the CA is configured to sign CRLs
kadonotakashi 0:8fdf9a60065b 1680 */
kadonotakashi 0:8fdf9a60065b 1681 #if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
kadonotakashi 0:8fdf9a60065b 1682 if( mbedtls_x509_crt_check_key_usage( ca, MBEDTLS_X509_KU_CRL_SIGN ) != 0 )
kadonotakashi 0:8fdf9a60065b 1683 {
kadonotakashi 0:8fdf9a60065b 1684 flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
kadonotakashi 0:8fdf9a60065b 1685 break;
kadonotakashi 0:8fdf9a60065b 1686 }
kadonotakashi 0:8fdf9a60065b 1687 #endif
kadonotakashi 0:8fdf9a60065b 1688
kadonotakashi 0:8fdf9a60065b 1689 /*
kadonotakashi 0:8fdf9a60065b 1690 * Check if CRL is correctly signed by the trusted CA
kadonotakashi 0:8fdf9a60065b 1691 */
kadonotakashi 0:8fdf9a60065b 1692 if( x509_profile_check_md_alg( profile, crl_list->sig_md ) != 0 )
kadonotakashi 0:8fdf9a60065b 1693 flags |= MBEDTLS_X509_BADCRL_BAD_MD;
kadonotakashi 0:8fdf9a60065b 1694
kadonotakashi 0:8fdf9a60065b 1695 if( x509_profile_check_pk_alg( profile, crl_list->sig_pk ) != 0 )
kadonotakashi 0:8fdf9a60065b 1696 flags |= MBEDTLS_X509_BADCRL_BAD_PK;
kadonotakashi 0:8fdf9a60065b 1697
kadonotakashi 0:8fdf9a60065b 1698 md_info = mbedtls_md_info_from_type( crl_list->sig_md );
kadonotakashi 0:8fdf9a60065b 1699 if( mbedtls_md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ) != 0 )
kadonotakashi 0:8fdf9a60065b 1700 {
kadonotakashi 0:8fdf9a60065b 1701 /* Note: this can't happen except after an internal error */
kadonotakashi 0:8fdf9a60065b 1702 flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
kadonotakashi 0:8fdf9a60065b 1703 break;
kadonotakashi 0:8fdf9a60065b 1704 }
kadonotakashi 0:8fdf9a60065b 1705
kadonotakashi 0:8fdf9a60065b 1706 if( x509_profile_check_key( profile, &ca->pk ) != 0 )
kadonotakashi 0:8fdf9a60065b 1707 flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
kadonotakashi 0:8fdf9a60065b 1708
kadonotakashi 0:8fdf9a60065b 1709 if( mbedtls_pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, &ca->pk,
kadonotakashi 0:8fdf9a60065b 1710 crl_list->sig_md, hash, mbedtls_md_get_size( md_info ),
kadonotakashi 0:8fdf9a60065b 1711 crl_list->sig.p, crl_list->sig.len ) != 0 )
kadonotakashi 0:8fdf9a60065b 1712 {
kadonotakashi 0:8fdf9a60065b 1713 flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
kadonotakashi 0:8fdf9a60065b 1714 break;
kadonotakashi 0:8fdf9a60065b 1715 }
kadonotakashi 0:8fdf9a60065b 1716
kadonotakashi 0:8fdf9a60065b 1717 /*
kadonotakashi 0:8fdf9a60065b 1718 * Check for validity of CRL (Do not drop out)
kadonotakashi 0:8fdf9a60065b 1719 */
kadonotakashi 0:8fdf9a60065b 1720 if( mbedtls_x509_time_is_past( &crl_list->next_update ) )
kadonotakashi 0:8fdf9a60065b 1721 flags |= MBEDTLS_X509_BADCRL_EXPIRED;
kadonotakashi 0:8fdf9a60065b 1722
kadonotakashi 0:8fdf9a60065b 1723 if( mbedtls_x509_time_is_future( &crl_list->this_update ) )
kadonotakashi 0:8fdf9a60065b 1724 flags |= MBEDTLS_X509_BADCRL_FUTURE;
kadonotakashi 0:8fdf9a60065b 1725
kadonotakashi 0:8fdf9a60065b 1726 /*
kadonotakashi 0:8fdf9a60065b 1727 * Check if certificate is revoked
kadonotakashi 0:8fdf9a60065b 1728 */
kadonotakashi 0:8fdf9a60065b 1729 if( mbedtls_x509_crt_is_revoked( crt, crl_list ) )
kadonotakashi 0:8fdf9a60065b 1730 {
kadonotakashi 0:8fdf9a60065b 1731 flags |= MBEDTLS_X509_BADCERT_REVOKED;
kadonotakashi 0:8fdf9a60065b 1732 break;
kadonotakashi 0:8fdf9a60065b 1733 }
kadonotakashi 0:8fdf9a60065b 1734
kadonotakashi 0:8fdf9a60065b 1735 crl_list = crl_list->next;
kadonotakashi 0:8fdf9a60065b 1736 }
kadonotakashi 0:8fdf9a60065b 1737
kadonotakashi 0:8fdf9a60065b 1738 return( flags );
kadonotakashi 0:8fdf9a60065b 1739 }
kadonotakashi 0:8fdf9a60065b 1740 #endif /* MBEDTLS_X509_CRL_PARSE_C */
kadonotakashi 0:8fdf9a60065b 1741
kadonotakashi 0:8fdf9a60065b 1742 /*
kadonotakashi 0:8fdf9a60065b 1743 * Like memcmp, but case-insensitive and always returns -1 if different
kadonotakashi 0:8fdf9a60065b 1744 */
kadonotakashi 0:8fdf9a60065b 1745 static int x509_memcasecmp( const void *s1, const void *s2, size_t len )
kadonotakashi 0:8fdf9a60065b 1746 {
kadonotakashi 0:8fdf9a60065b 1747 size_t i;
kadonotakashi 0:8fdf9a60065b 1748 unsigned char diff;
kadonotakashi 0:8fdf9a60065b 1749 const unsigned char *n1 = s1, *n2 = s2;
kadonotakashi 0:8fdf9a60065b 1750
kadonotakashi 0:8fdf9a60065b 1751 for( i = 0; i < len; i++ )
kadonotakashi 0:8fdf9a60065b 1752 {
kadonotakashi 0:8fdf9a60065b 1753 diff = n1[i] ^ n2[i];
kadonotakashi 0:8fdf9a60065b 1754
kadonotakashi 0:8fdf9a60065b 1755 if( diff == 0 )
kadonotakashi 0:8fdf9a60065b 1756 continue;
kadonotakashi 0:8fdf9a60065b 1757
kadonotakashi 0:8fdf9a60065b 1758 if( diff == 32 &&
kadonotakashi 0:8fdf9a60065b 1759 ( ( n1[i] >= 'a' && n1[i] <= 'z' ) ||
kadonotakashi 0:8fdf9a60065b 1760 ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) )
kadonotakashi 0:8fdf9a60065b 1761 {
kadonotakashi 0:8fdf9a60065b 1762 continue;
kadonotakashi 0:8fdf9a60065b 1763 }
kadonotakashi 0:8fdf9a60065b 1764
kadonotakashi 0:8fdf9a60065b 1765 return( -1 );
kadonotakashi 0:8fdf9a60065b 1766 }
kadonotakashi 0:8fdf9a60065b 1767
kadonotakashi 0:8fdf9a60065b 1768 return( 0 );
kadonotakashi 0:8fdf9a60065b 1769 }
kadonotakashi 0:8fdf9a60065b 1770
kadonotakashi 0:8fdf9a60065b 1771 /*
kadonotakashi 0:8fdf9a60065b 1772 * Return 0 if name matches wildcard, -1 otherwise
kadonotakashi 0:8fdf9a60065b 1773 */
kadonotakashi 0:8fdf9a60065b 1774 static int x509_check_wildcard( const char *cn, const mbedtls_x509_buf *name )
kadonotakashi 0:8fdf9a60065b 1775 {
kadonotakashi 0:8fdf9a60065b 1776 size_t i;
kadonotakashi 0:8fdf9a60065b 1777 size_t cn_idx = 0, cn_len = strlen( cn );
kadonotakashi 0:8fdf9a60065b 1778
kadonotakashi 0:8fdf9a60065b 1779 /* We can't have a match if there is no wildcard to match */
kadonotakashi 0:8fdf9a60065b 1780 if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' )
kadonotakashi 0:8fdf9a60065b 1781 return( -1 );
kadonotakashi 0:8fdf9a60065b 1782
kadonotakashi 0:8fdf9a60065b 1783 for( i = 0; i < cn_len; ++i )
kadonotakashi 0:8fdf9a60065b 1784 {
kadonotakashi 0:8fdf9a60065b 1785 if( cn[i] == '.' )
kadonotakashi 0:8fdf9a60065b 1786 {
kadonotakashi 0:8fdf9a60065b 1787 cn_idx = i;
kadonotakashi 0:8fdf9a60065b 1788 break;
kadonotakashi 0:8fdf9a60065b 1789 }
kadonotakashi 0:8fdf9a60065b 1790 }
kadonotakashi 0:8fdf9a60065b 1791
kadonotakashi 0:8fdf9a60065b 1792 if( cn_idx == 0 )
kadonotakashi 0:8fdf9a60065b 1793 return( -1 );
kadonotakashi 0:8fdf9a60065b 1794
kadonotakashi 0:8fdf9a60065b 1795 if( cn_len - cn_idx == name->len - 1 &&
kadonotakashi 0:8fdf9a60065b 1796 x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 )
kadonotakashi 0:8fdf9a60065b 1797 {
kadonotakashi 0:8fdf9a60065b 1798 return( 0 );
kadonotakashi 0:8fdf9a60065b 1799 }
kadonotakashi 0:8fdf9a60065b 1800
kadonotakashi 0:8fdf9a60065b 1801 return( -1 );
kadonotakashi 0:8fdf9a60065b 1802 }
kadonotakashi 0:8fdf9a60065b 1803
kadonotakashi 0:8fdf9a60065b 1804 /*
kadonotakashi 0:8fdf9a60065b 1805 * Compare two X.509 strings, case-insensitive, and allowing for some encoding
kadonotakashi 0:8fdf9a60065b 1806 * variations (but not all).
kadonotakashi 0:8fdf9a60065b 1807 *
kadonotakashi 0:8fdf9a60065b 1808 * Return 0 if equal, -1 otherwise.
kadonotakashi 0:8fdf9a60065b 1809 */
kadonotakashi 0:8fdf9a60065b 1810 static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b )
kadonotakashi 0:8fdf9a60065b 1811 {
kadonotakashi 0:8fdf9a60065b 1812 if( a->tag == b->tag &&
kadonotakashi 0:8fdf9a60065b 1813 a->len == b->len &&
kadonotakashi 0:8fdf9a60065b 1814 memcmp( a->p, b->p, b->len ) == 0 )
kadonotakashi 0:8fdf9a60065b 1815 {
kadonotakashi 0:8fdf9a60065b 1816 return( 0 );
kadonotakashi 0:8fdf9a60065b 1817 }
kadonotakashi 0:8fdf9a60065b 1818
kadonotakashi 0:8fdf9a60065b 1819 if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
kadonotakashi 0:8fdf9a60065b 1820 ( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
kadonotakashi 0:8fdf9a60065b 1821 a->len == b->len &&
kadonotakashi 0:8fdf9a60065b 1822 x509_memcasecmp( a->p, b->p, b->len ) == 0 )
kadonotakashi 0:8fdf9a60065b 1823 {
kadonotakashi 0:8fdf9a60065b 1824 return( 0 );
kadonotakashi 0:8fdf9a60065b 1825 }
kadonotakashi 0:8fdf9a60065b 1826
kadonotakashi 0:8fdf9a60065b 1827 return( -1 );
kadonotakashi 0:8fdf9a60065b 1828 }
kadonotakashi 0:8fdf9a60065b 1829
kadonotakashi 0:8fdf9a60065b 1830 /*
kadonotakashi 0:8fdf9a60065b 1831 * Compare two X.509 Names (aka rdnSequence).
kadonotakashi 0:8fdf9a60065b 1832 *
kadonotakashi 0:8fdf9a60065b 1833 * See RFC 5280 section 7.1, though we don't implement the whole algorithm:
kadonotakashi 0:8fdf9a60065b 1834 * we sometimes return unequal when the full algorithm would return equal,
kadonotakashi 0:8fdf9a60065b 1835 * but never the other way. (In particular, we don't do Unicode normalisation
kadonotakashi 0:8fdf9a60065b 1836 * or space folding.)
kadonotakashi 0:8fdf9a60065b 1837 *
kadonotakashi 0:8fdf9a60065b 1838 * Return 0 if equal, -1 otherwise.
kadonotakashi 0:8fdf9a60065b 1839 */
kadonotakashi 0:8fdf9a60065b 1840 static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b )
kadonotakashi 0:8fdf9a60065b 1841 {
kadonotakashi 0:8fdf9a60065b 1842 /* Avoid recursion, it might not be optimised by the compiler */
kadonotakashi 0:8fdf9a60065b 1843 while( a != NULL || b != NULL )
kadonotakashi 0:8fdf9a60065b 1844 {
kadonotakashi 0:8fdf9a60065b 1845 if( a == NULL || b == NULL )
kadonotakashi 0:8fdf9a60065b 1846 return( -1 );
kadonotakashi 0:8fdf9a60065b 1847
kadonotakashi 0:8fdf9a60065b 1848 /* type */
kadonotakashi 0:8fdf9a60065b 1849 if( a->oid.tag != b->oid.tag ||
kadonotakashi 0:8fdf9a60065b 1850 a->oid.len != b->oid.len ||
kadonotakashi 0:8fdf9a60065b 1851 memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 )
kadonotakashi 0:8fdf9a60065b 1852 {
kadonotakashi 0:8fdf9a60065b 1853 return( -1 );
kadonotakashi 0:8fdf9a60065b 1854 }
kadonotakashi 0:8fdf9a60065b 1855
kadonotakashi 0:8fdf9a60065b 1856 /* value */
kadonotakashi 0:8fdf9a60065b 1857 if( x509_string_cmp( &a->val, &b->val ) != 0 )
kadonotakashi 0:8fdf9a60065b 1858 return( -1 );
kadonotakashi 0:8fdf9a60065b 1859
kadonotakashi 0:8fdf9a60065b 1860 /* structure of the list of sets */
kadonotakashi 0:8fdf9a60065b 1861 if( a->next_merged != b->next_merged )
kadonotakashi 0:8fdf9a60065b 1862 return( -1 );
kadonotakashi 0:8fdf9a60065b 1863
kadonotakashi 0:8fdf9a60065b 1864 a = a->next;
kadonotakashi 0:8fdf9a60065b 1865 b = b->next;
kadonotakashi 0:8fdf9a60065b 1866 }
kadonotakashi 0:8fdf9a60065b 1867
kadonotakashi 0:8fdf9a60065b 1868 /* a == NULL == b */
kadonotakashi 0:8fdf9a60065b 1869 return( 0 );
kadonotakashi 0:8fdf9a60065b 1870 }
kadonotakashi 0:8fdf9a60065b 1871
kadonotakashi 0:8fdf9a60065b 1872 /*
kadonotakashi 0:8fdf9a60065b 1873 * Check the signature of a certificate by its parent
kadonotakashi 0:8fdf9a60065b 1874 */
kadonotakashi 0:8fdf9a60065b 1875 static int x509_crt_check_signature( const mbedtls_x509_crt *child,
kadonotakashi 0:8fdf9a60065b 1876 mbedtls_x509_crt *parent )
kadonotakashi 0:8fdf9a60065b 1877 {
kadonotakashi 0:8fdf9a60065b 1878 const mbedtls_md_info_t *md_info;
kadonotakashi 0:8fdf9a60065b 1879 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
kadonotakashi 0:8fdf9a60065b 1880
kadonotakashi 0:8fdf9a60065b 1881 md_info = mbedtls_md_info_from_type( child->sig_md );
kadonotakashi 0:8fdf9a60065b 1882 if( mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ) != 0 )
kadonotakashi 0:8fdf9a60065b 1883 {
kadonotakashi 0:8fdf9a60065b 1884 /* Note: this can't happen except after an internal error */
kadonotakashi 0:8fdf9a60065b 1885 return( -1 );
kadonotakashi 0:8fdf9a60065b 1886 }
kadonotakashi 0:8fdf9a60065b 1887
kadonotakashi 0:8fdf9a60065b 1888 if( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk,
kadonotakashi 0:8fdf9a60065b 1889 child->sig_md, hash, mbedtls_md_get_size( md_info ),
kadonotakashi 0:8fdf9a60065b 1890 child->sig.p, child->sig.len ) != 0 )
kadonotakashi 0:8fdf9a60065b 1891 {
kadonotakashi 0:8fdf9a60065b 1892 return( -1 );
kadonotakashi 0:8fdf9a60065b 1893 }
kadonotakashi 0:8fdf9a60065b 1894
kadonotakashi 0:8fdf9a60065b 1895 return( 0 );
kadonotakashi 0:8fdf9a60065b 1896 }
kadonotakashi 0:8fdf9a60065b 1897
kadonotakashi 0:8fdf9a60065b 1898 /*
kadonotakashi 0:8fdf9a60065b 1899 * Check if 'parent' is a suitable parent (signing CA) for 'child'.
kadonotakashi 0:8fdf9a60065b 1900 * Return 0 if yes, -1 if not.
kadonotakashi 0:8fdf9a60065b 1901 *
kadonotakashi 0:8fdf9a60065b 1902 * top means parent is a locally-trusted certificate
kadonotakashi 0:8fdf9a60065b 1903 */
kadonotakashi 0:8fdf9a60065b 1904 static int x509_crt_check_parent( const mbedtls_x509_crt *child,
kadonotakashi 0:8fdf9a60065b 1905 const mbedtls_x509_crt *parent,
kadonotakashi 0:8fdf9a60065b 1906 int top )
kadonotakashi 0:8fdf9a60065b 1907 {
kadonotakashi 0:8fdf9a60065b 1908 int need_ca_bit;
kadonotakashi 0:8fdf9a60065b 1909
kadonotakashi 0:8fdf9a60065b 1910 /* Parent must be the issuer */
kadonotakashi 0:8fdf9a60065b 1911 if( x509_name_cmp( &child->issuer, &parent->subject ) != 0 )
kadonotakashi 0:8fdf9a60065b 1912 return( -1 );
kadonotakashi 0:8fdf9a60065b 1913
kadonotakashi 0:8fdf9a60065b 1914 /* Parent must have the basicConstraints CA bit set as a general rule */
kadonotakashi 0:8fdf9a60065b 1915 need_ca_bit = 1;
kadonotakashi 0:8fdf9a60065b 1916
kadonotakashi 0:8fdf9a60065b 1917 /* Exception: v1/v2 certificates that are locally trusted. */
kadonotakashi 0:8fdf9a60065b 1918 if( top && parent->version < 3 )
kadonotakashi 0:8fdf9a60065b 1919 need_ca_bit = 0;
kadonotakashi 0:8fdf9a60065b 1920
kadonotakashi 0:8fdf9a60065b 1921 if( need_ca_bit && ! parent->ca_istrue )
kadonotakashi 0:8fdf9a60065b 1922 return( -1 );
kadonotakashi 0:8fdf9a60065b 1923
kadonotakashi 0:8fdf9a60065b 1924 #if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
kadonotakashi 0:8fdf9a60065b 1925 if( need_ca_bit &&
kadonotakashi 0:8fdf9a60065b 1926 mbedtls_x509_crt_check_key_usage( parent, MBEDTLS_X509_KU_KEY_CERT_SIGN ) != 0 )
kadonotakashi 0:8fdf9a60065b 1927 {
kadonotakashi 0:8fdf9a60065b 1928 return( -1 );
kadonotakashi 0:8fdf9a60065b 1929 }
kadonotakashi 0:8fdf9a60065b 1930 #endif
kadonotakashi 0:8fdf9a60065b 1931
kadonotakashi 0:8fdf9a60065b 1932 return( 0 );
kadonotakashi 0:8fdf9a60065b 1933 }
kadonotakashi 0:8fdf9a60065b 1934
kadonotakashi 0:8fdf9a60065b 1935 /*
kadonotakashi 0:8fdf9a60065b 1936 * Find a suitable parent for child in candidates, or return NULL.
kadonotakashi 0:8fdf9a60065b 1937 *
kadonotakashi 0:8fdf9a60065b 1938 * Here suitable is defined as:
kadonotakashi 0:8fdf9a60065b 1939 * 1. subject name matches child's issuer
kadonotakashi 0:8fdf9a60065b 1940 * 2. if necessary, the CA bit is set and key usage allows signing certs
kadonotakashi 0:8fdf9a60065b 1941 * 3. for trusted roots, the signature is correct
kadonotakashi 0:8fdf9a60065b 1942 * 4. pathlen constraints are satisfied
kadonotakashi 0:8fdf9a60065b 1943 *
kadonotakashi 0:8fdf9a60065b 1944 * If there's a suitable candidate which is also time-valid, return the first
kadonotakashi 0:8fdf9a60065b 1945 * such. Otherwise, return the first suitable candidate (or NULL if there is
kadonotakashi 0:8fdf9a60065b 1946 * none).
kadonotakashi 0:8fdf9a60065b 1947 *
kadonotakashi 0:8fdf9a60065b 1948 * The rationale for this rule is that someone could have a list of trusted
kadonotakashi 0:8fdf9a60065b 1949 * roots with two versions on the same root with different validity periods.
kadonotakashi 0:8fdf9a60065b 1950 * (At least one user reported having such a list and wanted it to just work.)
kadonotakashi 0:8fdf9a60065b 1951 * The reason we don't just require time-validity is that generally there is
kadonotakashi 0:8fdf9a60065b 1952 * only one version, and if it's expired we want the flags to state that
kadonotakashi 0:8fdf9a60065b 1953 * rather than NOT_TRUSTED, as would be the case if we required it here.
kadonotakashi 0:8fdf9a60065b 1954 *
kadonotakashi 0:8fdf9a60065b 1955 * The rationale for rule 3 (signature for trusted roots) is that users might
kadonotakashi 0:8fdf9a60065b 1956 * have two versions of the same CA with different keys in their list, and the
kadonotakashi 0:8fdf9a60065b 1957 * way we select the correct one is by checking the signature (as we don't
kadonotakashi 0:8fdf9a60065b 1958 * rely on key identifier extensions). (This is one way users might choose to
kadonotakashi 0:8fdf9a60065b 1959 * handle key rollover, another relies on self-issued certs, see [SIRO].)
kadonotakashi 0:8fdf9a60065b 1960 *
kadonotakashi 0:8fdf9a60065b 1961 * Arguments:
kadonotakashi 0:8fdf9a60065b 1962 * - [in] child: certificate for which we're looking for a parent
kadonotakashi 0:8fdf9a60065b 1963 * - [in] candidates: chained list of potential parents
kadonotakashi 0:8fdf9a60065b 1964 * - [in] top: 1 if candidates consists of trusted roots, ie we're at the top
kadonotakashi 0:8fdf9a60065b 1965 * of the chain, 0 otherwise
kadonotakashi 0:8fdf9a60065b 1966 * - [in] path_cnt: number of intermediates seen so far
kadonotakashi 0:8fdf9a60065b 1967 * - [in] self_cnt: number of self-signed intermediates seen so far
kadonotakashi 0:8fdf9a60065b 1968 * (will never be greater than path_cnt)
kadonotakashi 0:8fdf9a60065b 1969 *
kadonotakashi 0:8fdf9a60065b 1970 * Return value:
kadonotakashi 0:8fdf9a60065b 1971 * - the first suitable parent found (see above regarding time-validity)
kadonotakashi 0:8fdf9a60065b 1972 * - NULL if no suitable parent was found
kadonotakashi 0:8fdf9a60065b 1973 */
kadonotakashi 0:8fdf9a60065b 1974 static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child,
kadonotakashi 0:8fdf9a60065b 1975 mbedtls_x509_crt *candidates,
kadonotakashi 0:8fdf9a60065b 1976 int top,
kadonotakashi 0:8fdf9a60065b 1977 size_t path_cnt,
kadonotakashi 0:8fdf9a60065b 1978 size_t self_cnt )
kadonotakashi 0:8fdf9a60065b 1979 {
kadonotakashi 0:8fdf9a60065b 1980 mbedtls_x509_crt *parent, *badtime_parent = NULL;
kadonotakashi 0:8fdf9a60065b 1981
kadonotakashi 0:8fdf9a60065b 1982 for( parent = candidates; parent != NULL; parent = parent->next )
kadonotakashi 0:8fdf9a60065b 1983 {
kadonotakashi 0:8fdf9a60065b 1984 /* basic parenting skills (name, CA bit, key usage) */
kadonotakashi 0:8fdf9a60065b 1985 if( x509_crt_check_parent( child, parent, top ) != 0 )
kadonotakashi 0:8fdf9a60065b 1986 continue;
kadonotakashi 0:8fdf9a60065b 1987
kadonotakashi 0:8fdf9a60065b 1988 /* +1 because stored max_pathlen is 1 higher that the actual value */
kadonotakashi 0:8fdf9a60065b 1989 if( parent->max_pathlen > 0 &&
kadonotakashi 0:8fdf9a60065b 1990 (size_t) parent->max_pathlen < 1 + path_cnt - self_cnt )
kadonotakashi 0:8fdf9a60065b 1991 {
kadonotakashi 0:8fdf9a60065b 1992 continue;
kadonotakashi 0:8fdf9a60065b 1993 }
kadonotakashi 0:8fdf9a60065b 1994
kadonotakashi 0:8fdf9a60065b 1995 /* Signature */
kadonotakashi 0:8fdf9a60065b 1996 if( top && x509_crt_check_signature( child, parent ) != 0 )
kadonotakashi 0:8fdf9a60065b 1997 {
kadonotakashi 0:8fdf9a60065b 1998 continue;
kadonotakashi 0:8fdf9a60065b 1999 }
kadonotakashi 0:8fdf9a60065b 2000
kadonotakashi 0:8fdf9a60065b 2001 /* optional time check */
kadonotakashi 0:8fdf9a60065b 2002 if( mbedtls_x509_time_is_past( &parent->valid_to ) ||
kadonotakashi 0:8fdf9a60065b 2003 mbedtls_x509_time_is_future( &parent->valid_from ) )
kadonotakashi 0:8fdf9a60065b 2004 {
kadonotakashi 0:8fdf9a60065b 2005 if( badtime_parent == NULL )
kadonotakashi 0:8fdf9a60065b 2006 badtime_parent = parent;
kadonotakashi 0:8fdf9a60065b 2007
kadonotakashi 0:8fdf9a60065b 2008 continue;
kadonotakashi 0:8fdf9a60065b 2009 }
kadonotakashi 0:8fdf9a60065b 2010
kadonotakashi 0:8fdf9a60065b 2011 break;
kadonotakashi 0:8fdf9a60065b 2012 }
kadonotakashi 0:8fdf9a60065b 2013
kadonotakashi 0:8fdf9a60065b 2014 if( parent == NULL )
kadonotakashi 0:8fdf9a60065b 2015 parent = badtime_parent;
kadonotakashi 0:8fdf9a60065b 2016
kadonotakashi 0:8fdf9a60065b 2017 return( parent );
kadonotakashi 0:8fdf9a60065b 2018 }
kadonotakashi 0:8fdf9a60065b 2019
kadonotakashi 0:8fdf9a60065b 2020 /*
kadonotakashi 0:8fdf9a60065b 2021 * Find a parent in trusted CAs or the provided chain, or return NULL.
kadonotakashi 0:8fdf9a60065b 2022 *
kadonotakashi 0:8fdf9a60065b 2023 * Searches in trusted CAs first, and return the first suitable parent found
kadonotakashi 0:8fdf9a60065b 2024 * (see find_parent_in() for definition of suitable).
kadonotakashi 0:8fdf9a60065b 2025 *
kadonotakashi 0:8fdf9a60065b 2026 * Arguments:
kadonotakashi 0:8fdf9a60065b 2027 * - [in] child: certificate for which we're looking for a parent, followed
kadonotakashi 0:8fdf9a60065b 2028 * by a chain of possible intermediates
kadonotakashi 0:8fdf9a60065b 2029 * - [in] trust_ca: locally trusted CAs
kadonotakashi 0:8fdf9a60065b 2030 * - [out] 1 if parent was found in trust_ca, 0 if found in provided chain
kadonotakashi 0:8fdf9a60065b 2031 * - [in] path_cnt: number of intermediates seen so far
kadonotakashi 0:8fdf9a60065b 2032 * - [in] self_cnt: number of self-signed intermediates seen so far
kadonotakashi 0:8fdf9a60065b 2033 * (will always be no greater than path_cnt)
kadonotakashi 0:8fdf9a60065b 2034 *
kadonotakashi 0:8fdf9a60065b 2035 * Return value:
kadonotakashi 0:8fdf9a60065b 2036 * - the first suitable parent found (see find_parent_in() for "suitable")
kadonotakashi 0:8fdf9a60065b 2037 * - NULL if no suitable parent was found
kadonotakashi 0:8fdf9a60065b 2038 */
kadonotakashi 0:8fdf9a60065b 2039 static mbedtls_x509_crt *x509_crt_find_parent( mbedtls_x509_crt *child,
kadonotakashi 0:8fdf9a60065b 2040 mbedtls_x509_crt *trust_ca,
kadonotakashi 0:8fdf9a60065b 2041 int *parent_is_trusted,
kadonotakashi 0:8fdf9a60065b 2042 size_t path_cnt,
kadonotakashi 0:8fdf9a60065b 2043 size_t self_cnt )
kadonotakashi 0:8fdf9a60065b 2044 {
kadonotakashi 0:8fdf9a60065b 2045 mbedtls_x509_crt *parent;
kadonotakashi 0:8fdf9a60065b 2046
kadonotakashi 0:8fdf9a60065b 2047 /* Look for a parent in trusted CAs */
kadonotakashi 0:8fdf9a60065b 2048 *parent_is_trusted = 1;
kadonotakashi 0:8fdf9a60065b 2049 parent = x509_crt_find_parent_in( child, trust_ca, 1, path_cnt, self_cnt );
kadonotakashi 0:8fdf9a60065b 2050
kadonotakashi 0:8fdf9a60065b 2051 if( parent != NULL )
kadonotakashi 0:8fdf9a60065b 2052 return( parent );
kadonotakashi 0:8fdf9a60065b 2053
kadonotakashi 0:8fdf9a60065b 2054 /* Look for a parent upwards the chain */
kadonotakashi 0:8fdf9a60065b 2055 *parent_is_trusted = 0;
kadonotakashi 0:8fdf9a60065b 2056 return( x509_crt_find_parent_in( child, child->next, 0, path_cnt, self_cnt ) );
kadonotakashi 0:8fdf9a60065b 2057 }
kadonotakashi 0:8fdf9a60065b 2058
kadonotakashi 0:8fdf9a60065b 2059 /*
kadonotakashi 0:8fdf9a60065b 2060 * Check if an end-entity certificate is locally trusted
kadonotakashi 0:8fdf9a60065b 2061 *
kadonotakashi 0:8fdf9a60065b 2062 * Currently we require such certificates to be self-signed (actually only
kadonotakashi 0:8fdf9a60065b 2063 * check for self-issued as self-signatures are not checked)
kadonotakashi 0:8fdf9a60065b 2064 */
kadonotakashi 0:8fdf9a60065b 2065 static int x509_crt_check_ee_locally_trusted(
kadonotakashi 0:8fdf9a60065b 2066 mbedtls_x509_crt *crt,
kadonotakashi 0:8fdf9a60065b 2067 mbedtls_x509_crt *trust_ca )
kadonotakashi 0:8fdf9a60065b 2068 {
kadonotakashi 0:8fdf9a60065b 2069 mbedtls_x509_crt *cur;
kadonotakashi 0:8fdf9a60065b 2070
kadonotakashi 0:8fdf9a60065b 2071 /* must be self-issued */
kadonotakashi 0:8fdf9a60065b 2072 if( x509_name_cmp( &crt->issuer, &crt->subject ) != 0 )
kadonotakashi 0:8fdf9a60065b 2073 return( -1 );
kadonotakashi 0:8fdf9a60065b 2074
kadonotakashi 0:8fdf9a60065b 2075 /* look for an exact match with trusted cert */
kadonotakashi 0:8fdf9a60065b 2076 for( cur = trust_ca; cur != NULL; cur = cur->next )
kadonotakashi 0:8fdf9a60065b 2077 {
kadonotakashi 0:8fdf9a60065b 2078 if( crt->raw.len == cur->raw.len &&
kadonotakashi 0:8fdf9a60065b 2079 memcmp( crt->raw.p, cur->raw.p, crt->raw.len ) == 0 )
kadonotakashi 0:8fdf9a60065b 2080 {
kadonotakashi 0:8fdf9a60065b 2081 return( 0 );
kadonotakashi 0:8fdf9a60065b 2082 }
kadonotakashi 0:8fdf9a60065b 2083 }
kadonotakashi 0:8fdf9a60065b 2084
kadonotakashi 0:8fdf9a60065b 2085 /* too bad */
kadonotakashi 0:8fdf9a60065b 2086 return( -1 );
kadonotakashi 0:8fdf9a60065b 2087 }
kadonotakashi 0:8fdf9a60065b 2088
kadonotakashi 0:8fdf9a60065b 2089 /*
kadonotakashi 0:8fdf9a60065b 2090 * Build and verify a certificate chain
kadonotakashi 0:8fdf9a60065b 2091 *
kadonotakashi 0:8fdf9a60065b 2092 * Given a peer-provided list of certificates EE, C1, ..., Cn and
kadonotakashi 0:8fdf9a60065b 2093 * a list of trusted certs R1, ... Rp, try to build and verify a chain
kadonotakashi 0:8fdf9a60065b 2094 * EE, Ci1, ... Ciq [, Rj]
kadonotakashi 0:8fdf9a60065b 2095 * such that every cert in the chain is a child of the next one,
kadonotakashi 0:8fdf9a60065b 2096 * jumping to a trusted root as early as possible.
kadonotakashi 0:8fdf9a60065b 2097 *
kadonotakashi 0:8fdf9a60065b 2098 * Verify that chain and return it with flags for all issues found.
kadonotakashi 0:8fdf9a60065b 2099 *
kadonotakashi 0:8fdf9a60065b 2100 * Special cases:
kadonotakashi 0:8fdf9a60065b 2101 * - EE == Rj -> return a one-element list containing it
kadonotakashi 0:8fdf9a60065b 2102 * - EE, Ci1, ..., Ciq cannot be continued with a trusted root
kadonotakashi 0:8fdf9a60065b 2103 * -> return that chain with NOT_TRUSTED set on Ciq
kadonotakashi 0:8fdf9a60065b 2104 *
kadonotakashi 0:8fdf9a60065b 2105 * Arguments:
kadonotakashi 0:8fdf9a60065b 2106 * - [in] crt: the cert list EE, C1, ..., Cn
kadonotakashi 0:8fdf9a60065b 2107 * - [in] trust_ca: the trusted list R1, ..., Rp
kadonotakashi 0:8fdf9a60065b 2108 * - [in] ca_crl, profile: as in verify_with_profile()
kadonotakashi 0:8fdf9a60065b 2109 * - [out] ver_chain, chain_len: the built and verified chain
kadonotakashi 0:8fdf9a60065b 2110 *
kadonotakashi 0:8fdf9a60065b 2111 * Return value:
kadonotakashi 0:8fdf9a60065b 2112 * - non-zero if the chain could not be fully built and examined
kadonotakashi 0:8fdf9a60065b 2113 * - 0 is the chain was successfully built and examined,
kadonotakashi 0:8fdf9a60065b 2114 * even if it was found to be invalid
kadonotakashi 0:8fdf9a60065b 2115 */
kadonotakashi 0:8fdf9a60065b 2116 static int x509_crt_verify_chain(
kadonotakashi 0:8fdf9a60065b 2117 mbedtls_x509_crt *crt,
kadonotakashi 0:8fdf9a60065b 2118 mbedtls_x509_crt *trust_ca,
kadonotakashi 0:8fdf9a60065b 2119 mbedtls_x509_crl *ca_crl,
kadonotakashi 0:8fdf9a60065b 2120 const mbedtls_x509_crt_profile *profile,
kadonotakashi 0:8fdf9a60065b 2121 x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE],
kadonotakashi 0:8fdf9a60065b 2122 size_t *chain_len )
kadonotakashi 0:8fdf9a60065b 2123 {
kadonotakashi 0:8fdf9a60065b 2124 uint32_t *flags;
kadonotakashi 0:8fdf9a60065b 2125 mbedtls_x509_crt *child;
kadonotakashi 0:8fdf9a60065b 2126 mbedtls_x509_crt *parent;
kadonotakashi 0:8fdf9a60065b 2127 int parent_is_trusted = 0;
kadonotakashi 0:8fdf9a60065b 2128 int child_is_trusted = 0;
kadonotakashi 0:8fdf9a60065b 2129 size_t self_cnt = 0;
kadonotakashi 0:8fdf9a60065b 2130
kadonotakashi 0:8fdf9a60065b 2131 child = crt;
kadonotakashi 0:8fdf9a60065b 2132 *chain_len = 0;
kadonotakashi 0:8fdf9a60065b 2133
kadonotakashi 0:8fdf9a60065b 2134 while( 1 ) {
kadonotakashi 0:8fdf9a60065b 2135 /* Add certificate to the verification chain */
kadonotakashi 0:8fdf9a60065b 2136 ver_chain[*chain_len].crt = child;
kadonotakashi 0:8fdf9a60065b 2137 flags = &ver_chain[*chain_len].flags;
kadonotakashi 0:8fdf9a60065b 2138 ++*chain_len;
kadonotakashi 0:8fdf9a60065b 2139
kadonotakashi 0:8fdf9a60065b 2140 /* Check time-validity (all certificates) */
kadonotakashi 0:8fdf9a60065b 2141 if( mbedtls_x509_time_is_past( &child->valid_to ) )
kadonotakashi 0:8fdf9a60065b 2142 *flags |= MBEDTLS_X509_BADCERT_EXPIRED;
kadonotakashi 0:8fdf9a60065b 2143
kadonotakashi 0:8fdf9a60065b 2144 if( mbedtls_x509_time_is_future( &child->valid_from ) )
kadonotakashi 0:8fdf9a60065b 2145 *flags |= MBEDTLS_X509_BADCERT_FUTURE;
kadonotakashi 0:8fdf9a60065b 2146
kadonotakashi 0:8fdf9a60065b 2147 /* Stop here for trusted roots (but not for trusted EE certs) */
kadonotakashi 0:8fdf9a60065b 2148 if( child_is_trusted )
kadonotakashi 0:8fdf9a60065b 2149 return( 0 );
kadonotakashi 0:8fdf9a60065b 2150
kadonotakashi 0:8fdf9a60065b 2151 /* Check signature algorithm: MD & PK algs */
kadonotakashi 0:8fdf9a60065b 2152 if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 )
kadonotakashi 0:8fdf9a60065b 2153 *flags |= MBEDTLS_X509_BADCERT_BAD_MD;
kadonotakashi 0:8fdf9a60065b 2154
kadonotakashi 0:8fdf9a60065b 2155 if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 )
kadonotakashi 0:8fdf9a60065b 2156 *flags |= MBEDTLS_X509_BADCERT_BAD_PK;
kadonotakashi 0:8fdf9a60065b 2157
kadonotakashi 0:8fdf9a60065b 2158 /* Special case: EE certs that are locally trusted */
kadonotakashi 0:8fdf9a60065b 2159 if( *chain_len == 1 &&
kadonotakashi 0:8fdf9a60065b 2160 x509_crt_check_ee_locally_trusted( child, trust_ca ) == 0 )
kadonotakashi 0:8fdf9a60065b 2161 {
kadonotakashi 0:8fdf9a60065b 2162 return( 0 );
kadonotakashi 0:8fdf9a60065b 2163 }
kadonotakashi 0:8fdf9a60065b 2164
kadonotakashi 0:8fdf9a60065b 2165 /* Look for a parent in trusted CAs or up the chain */
kadonotakashi 0:8fdf9a60065b 2166 parent = x509_crt_find_parent( child, trust_ca, &parent_is_trusted,
kadonotakashi 0:8fdf9a60065b 2167 *chain_len - 1, self_cnt );
kadonotakashi 0:8fdf9a60065b 2168
kadonotakashi 0:8fdf9a60065b 2169 /* No parent? We're done here */
kadonotakashi 0:8fdf9a60065b 2170 if( parent == NULL )
kadonotakashi 0:8fdf9a60065b 2171 {
kadonotakashi 0:8fdf9a60065b 2172 *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
kadonotakashi 0:8fdf9a60065b 2173 return( 0 );
kadonotakashi 0:8fdf9a60065b 2174 }
kadonotakashi 0:8fdf9a60065b 2175
kadonotakashi 0:8fdf9a60065b 2176 /* Count intermediate self-issued (not necessarily self-signed) certs.
kadonotakashi 0:8fdf9a60065b 2177 * These can occur with some strategies for key rollover, see [SIRO],
kadonotakashi 0:8fdf9a60065b 2178 * and should be excluded from max_pathlen checks. */
kadonotakashi 0:8fdf9a60065b 2179 if( *chain_len != 1 &&
kadonotakashi 0:8fdf9a60065b 2180 x509_name_cmp( &child->issuer, &child->subject ) == 0 )
kadonotakashi 0:8fdf9a60065b 2181 {
kadonotakashi 0:8fdf9a60065b 2182 self_cnt++;
kadonotakashi 0:8fdf9a60065b 2183 }
kadonotakashi 0:8fdf9a60065b 2184
kadonotakashi 0:8fdf9a60065b 2185 /* path_cnt is 0 for the first intermediate CA,
kadonotakashi 0:8fdf9a60065b 2186 * and if parent is trusted it's not an intermediate CA */
kadonotakashi 0:8fdf9a60065b 2187 if( ! parent_is_trusted &&
kadonotakashi 0:8fdf9a60065b 2188 *chain_len > MBEDTLS_X509_MAX_INTERMEDIATE_CA )
kadonotakashi 0:8fdf9a60065b 2189 {
kadonotakashi 0:8fdf9a60065b 2190 /* return immediately to avoid overflow the chain array */
kadonotakashi 0:8fdf9a60065b 2191 return( MBEDTLS_ERR_X509_FATAL_ERROR );
kadonotakashi 0:8fdf9a60065b 2192 }
kadonotakashi 0:8fdf9a60065b 2193
kadonotakashi 0:8fdf9a60065b 2194 /* if parent is trusted, the signature was checked by find_parent() */
kadonotakashi 0:8fdf9a60065b 2195 if( ! parent_is_trusted && x509_crt_check_signature( child, parent ) != 0 )
kadonotakashi 0:8fdf9a60065b 2196 *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
kadonotakashi 0:8fdf9a60065b 2197
kadonotakashi 0:8fdf9a60065b 2198 /* check size of signing key */
kadonotakashi 0:8fdf9a60065b 2199 if( x509_profile_check_key( profile, &parent->pk ) != 0 )
kadonotakashi 0:8fdf9a60065b 2200 *flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
kadonotakashi 0:8fdf9a60065b 2201
kadonotakashi 0:8fdf9a60065b 2202 #if defined(MBEDTLS_X509_CRL_PARSE_C)
kadonotakashi 0:8fdf9a60065b 2203 /* Check trusted CA's CRL for the given crt */
kadonotakashi 0:8fdf9a60065b 2204 *flags |= x509_crt_verifycrl( child, parent, ca_crl, profile );
kadonotakashi 0:8fdf9a60065b 2205 #else
kadonotakashi 0:8fdf9a60065b 2206 (void) ca_crl;
kadonotakashi 0:8fdf9a60065b 2207 #endif
kadonotakashi 0:8fdf9a60065b 2208
kadonotakashi 0:8fdf9a60065b 2209 /* prepare for next iteration */
kadonotakashi 0:8fdf9a60065b 2210 child = parent;
kadonotakashi 0:8fdf9a60065b 2211 parent = NULL;
kadonotakashi 0:8fdf9a60065b 2212 child_is_trusted = parent_is_trusted;
kadonotakashi 0:8fdf9a60065b 2213 }
kadonotakashi 0:8fdf9a60065b 2214 }
kadonotakashi 0:8fdf9a60065b 2215
kadonotakashi 0:8fdf9a60065b 2216 /*
kadonotakashi 0:8fdf9a60065b 2217 * Check for CN match
kadonotakashi 0:8fdf9a60065b 2218 */
kadonotakashi 0:8fdf9a60065b 2219 static int x509_crt_check_cn( const mbedtls_x509_buf *name,
kadonotakashi 0:8fdf9a60065b 2220 const char *cn, size_t cn_len )
kadonotakashi 0:8fdf9a60065b 2221 {
kadonotakashi 0:8fdf9a60065b 2222 /* try exact match */
kadonotakashi 0:8fdf9a60065b 2223 if( name->len == cn_len &&
kadonotakashi 0:8fdf9a60065b 2224 x509_memcasecmp( cn, name->p, cn_len ) == 0 )
kadonotakashi 0:8fdf9a60065b 2225 {
kadonotakashi 0:8fdf9a60065b 2226 return( 0 );
kadonotakashi 0:8fdf9a60065b 2227 }
kadonotakashi 0:8fdf9a60065b 2228
kadonotakashi 0:8fdf9a60065b 2229 /* try wildcard match */
kadonotakashi 0:8fdf9a60065b 2230 if( x509_check_wildcard( cn, name ) == 0 )
kadonotakashi 0:8fdf9a60065b 2231 {
kadonotakashi 0:8fdf9a60065b 2232 return( 0 );
kadonotakashi 0:8fdf9a60065b 2233 }
kadonotakashi 0:8fdf9a60065b 2234
kadonotakashi 0:8fdf9a60065b 2235 return( -1 );
kadonotakashi 0:8fdf9a60065b 2236 }
kadonotakashi 0:8fdf9a60065b 2237
kadonotakashi 0:8fdf9a60065b 2238 /*
kadonotakashi 0:8fdf9a60065b 2239 * Verify the requested CN - only call this if cn is not NULL!
kadonotakashi 0:8fdf9a60065b 2240 */
kadonotakashi 0:8fdf9a60065b 2241 static void x509_crt_verify_name( const mbedtls_x509_crt *crt,
kadonotakashi 0:8fdf9a60065b 2242 const char *cn,
kadonotakashi 0:8fdf9a60065b 2243 uint32_t *flags )
kadonotakashi 0:8fdf9a60065b 2244 {
kadonotakashi 0:8fdf9a60065b 2245 const mbedtls_x509_name *name;
kadonotakashi 0:8fdf9a60065b 2246 const mbedtls_x509_sequence *cur;
kadonotakashi 0:8fdf9a60065b 2247 size_t cn_len = strlen( cn );
kadonotakashi 0:8fdf9a60065b 2248
kadonotakashi 0:8fdf9a60065b 2249 if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
kadonotakashi 0:8fdf9a60065b 2250 {
kadonotakashi 0:8fdf9a60065b 2251 for( cur = &crt->subject_alt_names; cur != NULL; cur = cur->next )
kadonotakashi 0:8fdf9a60065b 2252 {
kadonotakashi 0:8fdf9a60065b 2253 if( x509_crt_check_cn( &cur->buf, cn, cn_len ) == 0 )
kadonotakashi 0:8fdf9a60065b 2254 break;
kadonotakashi 0:8fdf9a60065b 2255 }
kadonotakashi 0:8fdf9a60065b 2256
kadonotakashi 0:8fdf9a60065b 2257 if( cur == NULL )
kadonotakashi 0:8fdf9a60065b 2258 *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
kadonotakashi 0:8fdf9a60065b 2259 }
kadonotakashi 0:8fdf9a60065b 2260 else
kadonotakashi 0:8fdf9a60065b 2261 {
kadonotakashi 0:8fdf9a60065b 2262 for( name = &crt->subject; name != NULL; name = name->next )
kadonotakashi 0:8fdf9a60065b 2263 {
kadonotakashi 0:8fdf9a60065b 2264 if( MBEDTLS_OID_CMP( MBEDTLS_OID_AT_CN, &name->oid ) == 0 &&
kadonotakashi 0:8fdf9a60065b 2265 x509_crt_check_cn( &name->val, cn, cn_len ) == 0 )
kadonotakashi 0:8fdf9a60065b 2266 {
kadonotakashi 0:8fdf9a60065b 2267 break;
kadonotakashi 0:8fdf9a60065b 2268 }
kadonotakashi 0:8fdf9a60065b 2269 }
kadonotakashi 0:8fdf9a60065b 2270
kadonotakashi 0:8fdf9a60065b 2271 if( name == NULL )
kadonotakashi 0:8fdf9a60065b 2272 *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
kadonotakashi 0:8fdf9a60065b 2273 }
kadonotakashi 0:8fdf9a60065b 2274 }
kadonotakashi 0:8fdf9a60065b 2275
kadonotakashi 0:8fdf9a60065b 2276 /*
kadonotakashi 0:8fdf9a60065b 2277 * Merge the flags for all certs in the chain, after calling callback
kadonotakashi 0:8fdf9a60065b 2278 */
kadonotakashi 0:8fdf9a60065b 2279 static int x509_crt_merge_flags_with_cb(
kadonotakashi 0:8fdf9a60065b 2280 uint32_t *flags,
kadonotakashi 0:8fdf9a60065b 2281 x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE],
kadonotakashi 0:8fdf9a60065b 2282 size_t chain_len,
kadonotakashi 0:8fdf9a60065b 2283 int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
kadonotakashi 0:8fdf9a60065b 2284 void *p_vrfy )
kadonotakashi 0:8fdf9a60065b 2285 {
kadonotakashi 0:8fdf9a60065b 2286 int ret;
kadonotakashi 0:8fdf9a60065b 2287 size_t i;
kadonotakashi 0:8fdf9a60065b 2288 uint32_t cur_flags;
kadonotakashi 0:8fdf9a60065b 2289
kadonotakashi 0:8fdf9a60065b 2290 for( i = chain_len; i != 0; --i )
kadonotakashi 0:8fdf9a60065b 2291 {
kadonotakashi 0:8fdf9a60065b 2292 cur_flags = ver_chain[i-1].flags;
kadonotakashi 0:8fdf9a60065b 2293
kadonotakashi 0:8fdf9a60065b 2294 if( NULL != f_vrfy )
kadonotakashi 0:8fdf9a60065b 2295 if( ( ret = f_vrfy( p_vrfy, ver_chain[i-1].crt, (int) i-1, &cur_flags ) ) != 0 )
kadonotakashi 0:8fdf9a60065b 2296 return( ret );
kadonotakashi 0:8fdf9a60065b 2297
kadonotakashi 0:8fdf9a60065b 2298 *flags |= cur_flags;
kadonotakashi 0:8fdf9a60065b 2299 }
kadonotakashi 0:8fdf9a60065b 2300
kadonotakashi 0:8fdf9a60065b 2301 return( 0 );
kadonotakashi 0:8fdf9a60065b 2302 }
kadonotakashi 0:8fdf9a60065b 2303
kadonotakashi 0:8fdf9a60065b 2304 /*
kadonotakashi 0:8fdf9a60065b 2305 * Verify the certificate validity
kadonotakashi 0:8fdf9a60065b 2306 */
kadonotakashi 0:8fdf9a60065b 2307 int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt,
kadonotakashi 0:8fdf9a60065b 2308 mbedtls_x509_crt *trust_ca,
kadonotakashi 0:8fdf9a60065b 2309 mbedtls_x509_crl *ca_crl,
kadonotakashi 0:8fdf9a60065b 2310 const char *cn, uint32_t *flags,
kadonotakashi 0:8fdf9a60065b 2311 int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
kadonotakashi 0:8fdf9a60065b 2312 void *p_vrfy )
kadonotakashi 0:8fdf9a60065b 2313 {
kadonotakashi 0:8fdf9a60065b 2314 return( mbedtls_x509_crt_verify_with_profile( crt, trust_ca, ca_crl,
kadonotakashi 0:8fdf9a60065b 2315 &mbedtls_x509_crt_profile_default, cn, flags, f_vrfy, p_vrfy ) );
kadonotakashi 0:8fdf9a60065b 2316 }
kadonotakashi 0:8fdf9a60065b 2317
kadonotakashi 0:8fdf9a60065b 2318 /*
kadonotakashi 0:8fdf9a60065b 2319 * Verify the certificate validity, with profile
kadonotakashi 0:8fdf9a60065b 2320 *
kadonotakashi 0:8fdf9a60065b 2321 * This function:
kadonotakashi 0:8fdf9a60065b 2322 * - checks the requested CN (if any)
kadonotakashi 0:8fdf9a60065b 2323 * - checks the type and size of the EE cert's key,
kadonotakashi 0:8fdf9a60065b 2324 * as that isn't done as part of chain building/verification currently
kadonotakashi 0:8fdf9a60065b 2325 * - builds and verifies the chain
kadonotakashi 0:8fdf9a60065b 2326 * - then calls the callback and merges the flags
kadonotakashi 0:8fdf9a60065b 2327 */
kadonotakashi 0:8fdf9a60065b 2328 int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
kadonotakashi 0:8fdf9a60065b 2329 mbedtls_x509_crt *trust_ca,
kadonotakashi 0:8fdf9a60065b 2330 mbedtls_x509_crl *ca_crl,
kadonotakashi 0:8fdf9a60065b 2331 const mbedtls_x509_crt_profile *profile,
kadonotakashi 0:8fdf9a60065b 2332 const char *cn, uint32_t *flags,
kadonotakashi 0:8fdf9a60065b 2333 int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
kadonotakashi 0:8fdf9a60065b 2334 void *p_vrfy )
kadonotakashi 0:8fdf9a60065b 2335 {
kadonotakashi 0:8fdf9a60065b 2336 int ret;
kadonotakashi 0:8fdf9a60065b 2337 mbedtls_pk_type_t pk_type;
kadonotakashi 0:8fdf9a60065b 2338 x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE];
kadonotakashi 0:8fdf9a60065b 2339 size_t chain_len;
kadonotakashi 0:8fdf9a60065b 2340 uint32_t *ee_flags = &ver_chain[0].flags;
kadonotakashi 0:8fdf9a60065b 2341
kadonotakashi 0:8fdf9a60065b 2342 *flags = 0;
kadonotakashi 0:8fdf9a60065b 2343 memset( ver_chain, 0, sizeof( ver_chain ) );
kadonotakashi 0:8fdf9a60065b 2344 chain_len = 0;
kadonotakashi 0:8fdf9a60065b 2345
kadonotakashi 0:8fdf9a60065b 2346 if( profile == NULL )
kadonotakashi 0:8fdf9a60065b 2347 {
kadonotakashi 0:8fdf9a60065b 2348 ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA;
kadonotakashi 0:8fdf9a60065b 2349 goto exit;
kadonotakashi 0:8fdf9a60065b 2350 }
kadonotakashi 0:8fdf9a60065b 2351
kadonotakashi 0:8fdf9a60065b 2352 /* check name if requested */
kadonotakashi 0:8fdf9a60065b 2353 if( cn != NULL )
kadonotakashi 0:8fdf9a60065b 2354 x509_crt_verify_name( crt, cn, ee_flags );
kadonotakashi 0:8fdf9a60065b 2355
kadonotakashi 0:8fdf9a60065b 2356 /* Check the type and size of the key */
kadonotakashi 0:8fdf9a60065b 2357 pk_type = mbedtls_pk_get_type( &crt->pk );
kadonotakashi 0:8fdf9a60065b 2358
kadonotakashi 0:8fdf9a60065b 2359 if( x509_profile_check_pk_alg( profile, pk_type ) != 0 )
kadonotakashi 0:8fdf9a60065b 2360 *ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK;
kadonotakashi 0:8fdf9a60065b 2361
kadonotakashi 0:8fdf9a60065b 2362 if( x509_profile_check_key( profile, &crt->pk ) != 0 )
kadonotakashi 0:8fdf9a60065b 2363 *ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
kadonotakashi 0:8fdf9a60065b 2364
kadonotakashi 0:8fdf9a60065b 2365 /* Check the chain */
kadonotakashi 0:8fdf9a60065b 2366 ret = x509_crt_verify_chain( crt, trust_ca, ca_crl, profile,
kadonotakashi 0:8fdf9a60065b 2367 ver_chain, &chain_len );
kadonotakashi 0:8fdf9a60065b 2368 if( ret != 0 )
kadonotakashi 0:8fdf9a60065b 2369 goto exit;
kadonotakashi 0:8fdf9a60065b 2370
kadonotakashi 0:8fdf9a60065b 2371 /* Build final flags, calling callback on the way if any */
kadonotakashi 0:8fdf9a60065b 2372 ret = x509_crt_merge_flags_with_cb( flags,
kadonotakashi 0:8fdf9a60065b 2373 ver_chain, chain_len, f_vrfy, p_vrfy );
kadonotakashi 0:8fdf9a60065b 2374
kadonotakashi 0:8fdf9a60065b 2375 exit:
kadonotakashi 0:8fdf9a60065b 2376 /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by
kadonotakashi 0:8fdf9a60065b 2377 * the SSL module for authmode optional, but non-zero return from the
kadonotakashi 0:8fdf9a60065b 2378 * callback means a fatal error so it shouldn't be ignored */
kadonotakashi 0:8fdf9a60065b 2379 if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED )
kadonotakashi 0:8fdf9a60065b 2380 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
kadonotakashi 0:8fdf9a60065b 2381
kadonotakashi 0:8fdf9a60065b 2382 if( ret != 0 )
kadonotakashi 0:8fdf9a60065b 2383 {
kadonotakashi 0:8fdf9a60065b 2384 *flags = (uint32_t) -1;
kadonotakashi 0:8fdf9a60065b 2385 return( ret );
kadonotakashi 0:8fdf9a60065b 2386 }
kadonotakashi 0:8fdf9a60065b 2387
kadonotakashi 0:8fdf9a60065b 2388 if( *flags != 0 )
kadonotakashi 0:8fdf9a60065b 2389 return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED );
kadonotakashi 0:8fdf9a60065b 2390
kadonotakashi 0:8fdf9a60065b 2391 return( 0 );
kadonotakashi 0:8fdf9a60065b 2392 }
kadonotakashi 0:8fdf9a60065b 2393
kadonotakashi 0:8fdf9a60065b 2394 /*
kadonotakashi 0:8fdf9a60065b 2395 * Initialize a certificate chain
kadonotakashi 0:8fdf9a60065b 2396 */
kadonotakashi 0:8fdf9a60065b 2397 void mbedtls_x509_crt_init( mbedtls_x509_crt *crt )
kadonotakashi 0:8fdf9a60065b 2398 {
kadonotakashi 0:8fdf9a60065b 2399 memset( crt, 0, sizeof(mbedtls_x509_crt) );
kadonotakashi 0:8fdf9a60065b 2400 }
kadonotakashi 0:8fdf9a60065b 2401
kadonotakashi 0:8fdf9a60065b 2402 /*
kadonotakashi 0:8fdf9a60065b 2403 * Unallocate all certificate data
kadonotakashi 0:8fdf9a60065b 2404 */
kadonotakashi 0:8fdf9a60065b 2405 void mbedtls_x509_crt_free( mbedtls_x509_crt *crt )
kadonotakashi 0:8fdf9a60065b 2406 {
kadonotakashi 0:8fdf9a60065b 2407 mbedtls_x509_crt *cert_cur = crt;
kadonotakashi 0:8fdf9a60065b 2408 mbedtls_x509_crt *cert_prv;
kadonotakashi 0:8fdf9a60065b 2409 mbedtls_x509_name *name_cur;
kadonotakashi 0:8fdf9a60065b 2410 mbedtls_x509_name *name_prv;
kadonotakashi 0:8fdf9a60065b 2411 mbedtls_x509_sequence *seq_cur;
kadonotakashi 0:8fdf9a60065b 2412 mbedtls_x509_sequence *seq_prv;
kadonotakashi 0:8fdf9a60065b 2413
kadonotakashi 0:8fdf9a60065b 2414 if( crt == NULL )
kadonotakashi 0:8fdf9a60065b 2415 return;
kadonotakashi 0:8fdf9a60065b 2416
kadonotakashi 0:8fdf9a60065b 2417 do
kadonotakashi 0:8fdf9a60065b 2418 {
kadonotakashi 0:8fdf9a60065b 2419 mbedtls_pk_free( &cert_cur->pk );
kadonotakashi 0:8fdf9a60065b 2420
kadonotakashi 0:8fdf9a60065b 2421 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
kadonotakashi 0:8fdf9a60065b 2422 mbedtls_free( cert_cur->sig_opts );
kadonotakashi 0:8fdf9a60065b 2423 #endif
kadonotakashi 0:8fdf9a60065b 2424
kadonotakashi 0:8fdf9a60065b 2425 name_cur = cert_cur->issuer.next;
kadonotakashi 0:8fdf9a60065b 2426 while( name_cur != NULL )
kadonotakashi 0:8fdf9a60065b 2427 {
kadonotakashi 0:8fdf9a60065b 2428 name_prv = name_cur;
kadonotakashi 0:8fdf9a60065b 2429 name_cur = name_cur->next;
kadonotakashi 0:8fdf9a60065b 2430 mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) );
kadonotakashi 0:8fdf9a60065b 2431 mbedtls_free( name_prv );
kadonotakashi 0:8fdf9a60065b 2432 }
kadonotakashi 0:8fdf9a60065b 2433
kadonotakashi 0:8fdf9a60065b 2434 name_cur = cert_cur->subject.next;
kadonotakashi 0:8fdf9a60065b 2435 while( name_cur != NULL )
kadonotakashi 0:8fdf9a60065b 2436 {
kadonotakashi 0:8fdf9a60065b 2437 name_prv = name_cur;
kadonotakashi 0:8fdf9a60065b 2438 name_cur = name_cur->next;
kadonotakashi 0:8fdf9a60065b 2439 mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) );
kadonotakashi 0:8fdf9a60065b 2440 mbedtls_free( name_prv );
kadonotakashi 0:8fdf9a60065b 2441 }
kadonotakashi 0:8fdf9a60065b 2442
kadonotakashi 0:8fdf9a60065b 2443 seq_cur = cert_cur->ext_key_usage.next;
kadonotakashi 0:8fdf9a60065b 2444 while( seq_cur != NULL )
kadonotakashi 0:8fdf9a60065b 2445 {
kadonotakashi 0:8fdf9a60065b 2446 seq_prv = seq_cur;
kadonotakashi 0:8fdf9a60065b 2447 seq_cur = seq_cur->next;
kadonotakashi 0:8fdf9a60065b 2448 mbedtls_platform_zeroize( seq_prv,
kadonotakashi 0:8fdf9a60065b 2449 sizeof( mbedtls_x509_sequence ) );
kadonotakashi 0:8fdf9a60065b 2450 mbedtls_free( seq_prv );
kadonotakashi 0:8fdf9a60065b 2451 }
kadonotakashi 0:8fdf9a60065b 2452
kadonotakashi 0:8fdf9a60065b 2453 seq_cur = cert_cur->subject_alt_names.next;
kadonotakashi 0:8fdf9a60065b 2454 while( seq_cur != NULL )
kadonotakashi 0:8fdf9a60065b 2455 {
kadonotakashi 0:8fdf9a60065b 2456 seq_prv = seq_cur;
kadonotakashi 0:8fdf9a60065b 2457 seq_cur = seq_cur->next;
kadonotakashi 0:8fdf9a60065b 2458 mbedtls_platform_zeroize( seq_prv,
kadonotakashi 0:8fdf9a60065b 2459 sizeof( mbedtls_x509_sequence ) );
kadonotakashi 0:8fdf9a60065b 2460 mbedtls_free( seq_prv );
kadonotakashi 0:8fdf9a60065b 2461 }
kadonotakashi 0:8fdf9a60065b 2462
kadonotakashi 0:8fdf9a60065b 2463 if( cert_cur->raw.p != NULL )
kadonotakashi 0:8fdf9a60065b 2464 {
kadonotakashi 0:8fdf9a60065b 2465 mbedtls_platform_zeroize( cert_cur->raw.p, cert_cur->raw.len );
kadonotakashi 0:8fdf9a60065b 2466 mbedtls_free( cert_cur->raw.p );
kadonotakashi 0:8fdf9a60065b 2467 }
kadonotakashi 0:8fdf9a60065b 2468
kadonotakashi 0:8fdf9a60065b 2469 cert_cur = cert_cur->next;
kadonotakashi 0:8fdf9a60065b 2470 }
kadonotakashi 0:8fdf9a60065b 2471 while( cert_cur != NULL );
kadonotakashi 0:8fdf9a60065b 2472
kadonotakashi 0:8fdf9a60065b 2473 cert_cur = crt;
kadonotakashi 0:8fdf9a60065b 2474 do
kadonotakashi 0:8fdf9a60065b 2475 {
kadonotakashi 0:8fdf9a60065b 2476 cert_prv = cert_cur;
kadonotakashi 0:8fdf9a60065b 2477 cert_cur = cert_cur->next;
kadonotakashi 0:8fdf9a60065b 2478
kadonotakashi 0:8fdf9a60065b 2479 mbedtls_platform_zeroize( cert_prv, sizeof( mbedtls_x509_crt ) );
kadonotakashi 0:8fdf9a60065b 2480 if( cert_prv != crt )
kadonotakashi 0:8fdf9a60065b 2481 mbedtls_free( cert_prv );
kadonotakashi 0:8fdf9a60065b 2482 }
kadonotakashi 0:8fdf9a60065b 2483 while( cert_cur != NULL );
kadonotakashi 0:8fdf9a60065b 2484 }
kadonotakashi 0:8fdf9a60065b 2485
kadonotakashi 0:8fdf9a60065b 2486 #endif /* MBEDTLS_X509_CRT_PARSE_C */