mbed-os5 only for TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Committer:
kenjiArai
Date:
Tue Dec 17 23:23:45 2019 +0000
Revision:
0:5b88d5760320
Child:
1:9db0e321a9f4
mbed-os5 only for TYBLE16

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kenjiArai 0:5b88d5760320 1 /*
kenjiArai 0:5b88d5760320 2 * X.509 certificate parsing and verification
kenjiArai 0:5b88d5760320 3 *
kenjiArai 0:5b88d5760320 4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
kenjiArai 0:5b88d5760320 5 * SPDX-License-Identifier: Apache-2.0
kenjiArai 0:5b88d5760320 6 *
kenjiArai 0:5b88d5760320 7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
kenjiArai 0:5b88d5760320 8 * not use this file except in compliance with the License.
kenjiArai 0:5b88d5760320 9 * You may obtain a copy of the License at
kenjiArai 0:5b88d5760320 10 *
kenjiArai 0:5b88d5760320 11 * http://www.apache.org/licenses/LICENSE-2.0
kenjiArai 0:5b88d5760320 12 *
kenjiArai 0:5b88d5760320 13 * Unless required by applicable law or agreed to in writing, software
kenjiArai 0:5b88d5760320 14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
kenjiArai 0:5b88d5760320 15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kenjiArai 0:5b88d5760320 16 * See the License for the specific language governing permissions and
kenjiArai 0:5b88d5760320 17 * limitations under the License.
kenjiArai 0:5b88d5760320 18 *
kenjiArai 0:5b88d5760320 19 * This file is part of mbed TLS (https://tls.mbed.org)
kenjiArai 0:5b88d5760320 20 */
kenjiArai 0:5b88d5760320 21 /*
kenjiArai 0:5b88d5760320 22 * The ITU-T X.509 standard defines a certificate format for PKI.
kenjiArai 0:5b88d5760320 23 *
kenjiArai 0:5b88d5760320 24 * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)
kenjiArai 0:5b88d5760320 25 * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
kenjiArai 0:5b88d5760320 26 * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
kenjiArai 0:5b88d5760320 27 *
kenjiArai 0:5b88d5760320 28 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
kenjiArai 0:5b88d5760320 29 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
kenjiArai 0:5b88d5760320 30 *
kenjiArai 0:5b88d5760320 31 * [SIRO] https://cabforum.org/wp-content/uploads/Chunghwatelecom201503cabforumV4.pdf
kenjiArai 0:5b88d5760320 32 */
kenjiArai 0:5b88d5760320 33
kenjiArai 0:5b88d5760320 34 #if !defined(MBEDTLS_CONFIG_FILE)
kenjiArai 0:5b88d5760320 35 #include "mbedtls/config.h"
kenjiArai 0:5b88d5760320 36 #else
kenjiArai 0:5b88d5760320 37 #include MBEDTLS_CONFIG_FILE
kenjiArai 0:5b88d5760320 38 #endif
kenjiArai 0:5b88d5760320 39
kenjiArai 0:5b88d5760320 40 #if defined(MBEDTLS_X509_CRT_PARSE_C)
kenjiArai 0:5b88d5760320 41
kenjiArai 0:5b88d5760320 42 #include "mbedtls/x509_crt.h"
kenjiArai 0:5b88d5760320 43 #include "mbedtls/oid.h"
kenjiArai 0:5b88d5760320 44 #include "mbedtls/platform_util.h"
kenjiArai 0:5b88d5760320 45
kenjiArai 0:5b88d5760320 46 #include <string.h>
kenjiArai 0:5b88d5760320 47
kenjiArai 0:5b88d5760320 48 #if defined(MBEDTLS_PEM_PARSE_C)
kenjiArai 0:5b88d5760320 49 #include "mbedtls/pem.h"
kenjiArai 0:5b88d5760320 50 #endif
kenjiArai 0:5b88d5760320 51
kenjiArai 0:5b88d5760320 52 #if defined(MBEDTLS_USE_PSA_CRYPTO)
kenjiArai 0:5b88d5760320 53 #include "psa/crypto.h"
kenjiArai 0:5b88d5760320 54 #include "mbedtls/psa_util.h"
kenjiArai 0:5b88d5760320 55 #endif
kenjiArai 0:5b88d5760320 56
kenjiArai 0:5b88d5760320 57 #if defined(MBEDTLS_PLATFORM_C)
kenjiArai 0:5b88d5760320 58 #include "mbedtls/platform.h"
kenjiArai 0:5b88d5760320 59 #else
kenjiArai 0:5b88d5760320 60 #include <stdio.h>
kenjiArai 0:5b88d5760320 61 #include <stdlib.h>
kenjiArai 0:5b88d5760320 62 #define mbedtls_free free
kenjiArai 0:5b88d5760320 63 #define mbedtls_calloc calloc
kenjiArai 0:5b88d5760320 64 #define mbedtls_snprintf snprintf
kenjiArai 0:5b88d5760320 65 #endif
kenjiArai 0:5b88d5760320 66
kenjiArai 0:5b88d5760320 67 #if defined(MBEDTLS_THREADING_C)
kenjiArai 0:5b88d5760320 68 #include "mbedtls/threading.h"
kenjiArai 0:5b88d5760320 69 #endif
kenjiArai 0:5b88d5760320 70
kenjiArai 0:5b88d5760320 71 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
kenjiArai 0:5b88d5760320 72 #include <windows.h>
kenjiArai 0:5b88d5760320 73 #else
kenjiArai 0:5b88d5760320 74 #include <time.h>
kenjiArai 0:5b88d5760320 75 #endif
kenjiArai 0:5b88d5760320 76
kenjiArai 0:5b88d5760320 77 #if defined(MBEDTLS_FS_IO)
kenjiArai 0:5b88d5760320 78 #include <stdio.h>
kenjiArai 0:5b88d5760320 79 #if !defined(_WIN32) || defined(EFIX64) || defined(EFI32)
kenjiArai 0:5b88d5760320 80 #include <sys/types.h>
kenjiArai 0:5b88d5760320 81 #include <sys/stat.h>
kenjiArai 0:5b88d5760320 82 #include <dirent.h>
kenjiArai 0:5b88d5760320 83 #endif /* !_WIN32 || EFIX64 || EFI32 */
kenjiArai 0:5b88d5760320 84 #endif
kenjiArai 0:5b88d5760320 85
kenjiArai 0:5b88d5760320 86 /*
kenjiArai 0:5b88d5760320 87 * Item in a verification chain: cert and flags for it
kenjiArai 0:5b88d5760320 88 */
kenjiArai 0:5b88d5760320 89 typedef struct {
kenjiArai 0:5b88d5760320 90 mbedtls_x509_crt *crt;
kenjiArai 0:5b88d5760320 91 uint32_t flags;
kenjiArai 0:5b88d5760320 92 } x509_crt_verify_chain_item;
kenjiArai 0:5b88d5760320 93
kenjiArai 0:5b88d5760320 94 /*
kenjiArai 0:5b88d5760320 95 * Max size of verification chain: end-entity + intermediates + trusted root
kenjiArai 0:5b88d5760320 96 */
kenjiArai 0:5b88d5760320 97 #define X509_MAX_VERIFY_CHAIN_SIZE ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 )
kenjiArai 0:5b88d5760320 98
kenjiArai 0:5b88d5760320 99 /*
kenjiArai 0:5b88d5760320 100 * Default profile
kenjiArai 0:5b88d5760320 101 */
kenjiArai 0:5b88d5760320 102 const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default =
kenjiArai 0:5b88d5760320 103 {
kenjiArai 0:5b88d5760320 104 #if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES)
kenjiArai 0:5b88d5760320 105 /* Allow SHA-1 (weak, but still safe in controlled environments) */
kenjiArai 0:5b88d5760320 106 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) |
kenjiArai 0:5b88d5760320 107 #endif
kenjiArai 0:5b88d5760320 108 /* Only SHA-2 hashes */
kenjiArai 0:5b88d5760320 109 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) |
kenjiArai 0:5b88d5760320 110 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
kenjiArai 0:5b88d5760320 111 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
kenjiArai 0:5b88d5760320 112 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
kenjiArai 0:5b88d5760320 113 0xFFFFFFF, /* Any PK alg */
kenjiArai 0:5b88d5760320 114 0xFFFFFFF, /* Any curve */
kenjiArai 0:5b88d5760320 115 2048,
kenjiArai 0:5b88d5760320 116 };
kenjiArai 0:5b88d5760320 117
kenjiArai 0:5b88d5760320 118 /*
kenjiArai 0:5b88d5760320 119 * Next-default profile
kenjiArai 0:5b88d5760320 120 */
kenjiArai 0:5b88d5760320 121 const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next =
kenjiArai 0:5b88d5760320 122 {
kenjiArai 0:5b88d5760320 123 /* Hashes from SHA-256 and above */
kenjiArai 0:5b88d5760320 124 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
kenjiArai 0:5b88d5760320 125 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
kenjiArai 0:5b88d5760320 126 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
kenjiArai 0:5b88d5760320 127 0xFFFFFFF, /* Any PK alg */
kenjiArai 0:5b88d5760320 128 #if defined(MBEDTLS_ECP_C)
kenjiArai 0:5b88d5760320 129 /* Curves at or above 128-bit security level */
kenjiArai 0:5b88d5760320 130 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) |
kenjiArai 0:5b88d5760320 131 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ) |
kenjiArai 0:5b88d5760320 132 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP521R1 ) |
kenjiArai 0:5b88d5760320 133 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP256R1 ) |
kenjiArai 0:5b88d5760320 134 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP384R1 ) |
kenjiArai 0:5b88d5760320 135 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP512R1 ) |
kenjiArai 0:5b88d5760320 136 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256K1 ),
kenjiArai 0:5b88d5760320 137 #else
kenjiArai 0:5b88d5760320 138 0,
kenjiArai 0:5b88d5760320 139 #endif
kenjiArai 0:5b88d5760320 140 2048,
kenjiArai 0:5b88d5760320 141 };
kenjiArai 0:5b88d5760320 142
kenjiArai 0:5b88d5760320 143 /*
kenjiArai 0:5b88d5760320 144 * NSA Suite B Profile
kenjiArai 0:5b88d5760320 145 */
kenjiArai 0:5b88d5760320 146 const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb =
kenjiArai 0:5b88d5760320 147 {
kenjiArai 0:5b88d5760320 148 /* Only SHA-256 and 384 */
kenjiArai 0:5b88d5760320 149 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
kenjiArai 0:5b88d5760320 150 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ),
kenjiArai 0:5b88d5760320 151 /* Only ECDSA */
kenjiArai 0:5b88d5760320 152 MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ) |
kenjiArai 0:5b88d5760320 153 MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECKEY ),
kenjiArai 0:5b88d5760320 154 #if defined(MBEDTLS_ECP_C)
kenjiArai 0:5b88d5760320 155 /* Only NIST P-256 and P-384 */
kenjiArai 0:5b88d5760320 156 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) |
kenjiArai 0:5b88d5760320 157 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ),
kenjiArai 0:5b88d5760320 158 #else
kenjiArai 0:5b88d5760320 159 0,
kenjiArai 0:5b88d5760320 160 #endif
kenjiArai 0:5b88d5760320 161 0,
kenjiArai 0:5b88d5760320 162 };
kenjiArai 0:5b88d5760320 163
kenjiArai 0:5b88d5760320 164 /*
kenjiArai 0:5b88d5760320 165 * Check md_alg against profile
kenjiArai 0:5b88d5760320 166 * Return 0 if md_alg is acceptable for this profile, -1 otherwise
kenjiArai 0:5b88d5760320 167 */
kenjiArai 0:5b88d5760320 168 static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile,
kenjiArai 0:5b88d5760320 169 mbedtls_md_type_t md_alg )
kenjiArai 0:5b88d5760320 170 {
kenjiArai 0:5b88d5760320 171 if( md_alg == MBEDTLS_MD_NONE )
kenjiArai 0:5b88d5760320 172 return( -1 );
kenjiArai 0:5b88d5760320 173
kenjiArai 0:5b88d5760320 174 if( ( profile->allowed_mds & MBEDTLS_X509_ID_FLAG( md_alg ) ) != 0 )
kenjiArai 0:5b88d5760320 175 return( 0 );
kenjiArai 0:5b88d5760320 176
kenjiArai 0:5b88d5760320 177 return( -1 );
kenjiArai 0:5b88d5760320 178 }
kenjiArai 0:5b88d5760320 179
kenjiArai 0:5b88d5760320 180 /*
kenjiArai 0:5b88d5760320 181 * Check pk_alg against profile
kenjiArai 0:5b88d5760320 182 * Return 0 if pk_alg is acceptable for this profile, -1 otherwise
kenjiArai 0:5b88d5760320 183 */
kenjiArai 0:5b88d5760320 184 static int x509_profile_check_pk_alg( const mbedtls_x509_crt_profile *profile,
kenjiArai 0:5b88d5760320 185 mbedtls_pk_type_t pk_alg )
kenjiArai 0:5b88d5760320 186 {
kenjiArai 0:5b88d5760320 187 if( pk_alg == MBEDTLS_PK_NONE )
kenjiArai 0:5b88d5760320 188 return( -1 );
kenjiArai 0:5b88d5760320 189
kenjiArai 0:5b88d5760320 190 if( ( profile->allowed_pks & MBEDTLS_X509_ID_FLAG( pk_alg ) ) != 0 )
kenjiArai 0:5b88d5760320 191 return( 0 );
kenjiArai 0:5b88d5760320 192
kenjiArai 0:5b88d5760320 193 return( -1 );
kenjiArai 0:5b88d5760320 194 }
kenjiArai 0:5b88d5760320 195
kenjiArai 0:5b88d5760320 196 /*
kenjiArai 0:5b88d5760320 197 * Check key against profile
kenjiArai 0:5b88d5760320 198 * Return 0 if pk is acceptable for this profile, -1 otherwise
kenjiArai 0:5b88d5760320 199 */
kenjiArai 0:5b88d5760320 200 static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile,
kenjiArai 0:5b88d5760320 201 const mbedtls_pk_context *pk )
kenjiArai 0:5b88d5760320 202 {
kenjiArai 0:5b88d5760320 203 const mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type( pk );
kenjiArai 0:5b88d5760320 204
kenjiArai 0:5b88d5760320 205 #if defined(MBEDTLS_RSA_C)
kenjiArai 0:5b88d5760320 206 if( pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS )
kenjiArai 0:5b88d5760320 207 {
kenjiArai 0:5b88d5760320 208 if( mbedtls_pk_get_bitlen( pk ) >= profile->rsa_min_bitlen )
kenjiArai 0:5b88d5760320 209 return( 0 );
kenjiArai 0:5b88d5760320 210
kenjiArai 0:5b88d5760320 211 return( -1 );
kenjiArai 0:5b88d5760320 212 }
kenjiArai 0:5b88d5760320 213 #endif
kenjiArai 0:5b88d5760320 214
kenjiArai 0:5b88d5760320 215 #if defined(MBEDTLS_ECP_C)
kenjiArai 0:5b88d5760320 216 if( pk_alg == MBEDTLS_PK_ECDSA ||
kenjiArai 0:5b88d5760320 217 pk_alg == MBEDTLS_PK_ECKEY ||
kenjiArai 0:5b88d5760320 218 pk_alg == MBEDTLS_PK_ECKEY_DH )
kenjiArai 0:5b88d5760320 219 {
kenjiArai 0:5b88d5760320 220 const mbedtls_ecp_group_id gid = mbedtls_pk_ec( *pk )->grp.id;
kenjiArai 0:5b88d5760320 221
kenjiArai 0:5b88d5760320 222 if( gid == MBEDTLS_ECP_DP_NONE )
kenjiArai 0:5b88d5760320 223 return( -1 );
kenjiArai 0:5b88d5760320 224
kenjiArai 0:5b88d5760320 225 if( ( profile->allowed_curves & MBEDTLS_X509_ID_FLAG( gid ) ) != 0 )
kenjiArai 0:5b88d5760320 226 return( 0 );
kenjiArai 0:5b88d5760320 227
kenjiArai 0:5b88d5760320 228 return( -1 );
kenjiArai 0:5b88d5760320 229 }
kenjiArai 0:5b88d5760320 230 #endif
kenjiArai 0:5b88d5760320 231
kenjiArai 0:5b88d5760320 232 return( -1 );
kenjiArai 0:5b88d5760320 233 }
kenjiArai 0:5b88d5760320 234
kenjiArai 0:5b88d5760320 235 /*
kenjiArai 0:5b88d5760320 236 * Like memcmp, but case-insensitive and always returns -1 if different
kenjiArai 0:5b88d5760320 237 */
kenjiArai 0:5b88d5760320 238 static int x509_memcasecmp( const void *s1, const void *s2, size_t len )
kenjiArai 0:5b88d5760320 239 {
kenjiArai 0:5b88d5760320 240 size_t i;
kenjiArai 0:5b88d5760320 241 unsigned char diff;
kenjiArai 0:5b88d5760320 242 const unsigned char *n1 = s1, *n2 = s2;
kenjiArai 0:5b88d5760320 243
kenjiArai 0:5b88d5760320 244 for( i = 0; i < len; i++ )
kenjiArai 0:5b88d5760320 245 {
kenjiArai 0:5b88d5760320 246 diff = n1[i] ^ n2[i];
kenjiArai 0:5b88d5760320 247
kenjiArai 0:5b88d5760320 248 if( diff == 0 )
kenjiArai 0:5b88d5760320 249 continue;
kenjiArai 0:5b88d5760320 250
kenjiArai 0:5b88d5760320 251 if( diff == 32 &&
kenjiArai 0:5b88d5760320 252 ( ( n1[i] >= 'a' && n1[i] <= 'z' ) ||
kenjiArai 0:5b88d5760320 253 ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) )
kenjiArai 0:5b88d5760320 254 {
kenjiArai 0:5b88d5760320 255 continue;
kenjiArai 0:5b88d5760320 256 }
kenjiArai 0:5b88d5760320 257
kenjiArai 0:5b88d5760320 258 return( -1 );
kenjiArai 0:5b88d5760320 259 }
kenjiArai 0:5b88d5760320 260
kenjiArai 0:5b88d5760320 261 return( 0 );
kenjiArai 0:5b88d5760320 262 }
kenjiArai 0:5b88d5760320 263
kenjiArai 0:5b88d5760320 264 /*
kenjiArai 0:5b88d5760320 265 * Return 0 if name matches wildcard, -1 otherwise
kenjiArai 0:5b88d5760320 266 */
kenjiArai 0:5b88d5760320 267 static int x509_check_wildcard( const char *cn, const mbedtls_x509_buf *name )
kenjiArai 0:5b88d5760320 268 {
kenjiArai 0:5b88d5760320 269 size_t i;
kenjiArai 0:5b88d5760320 270 size_t cn_idx = 0, cn_len = strlen( cn );
kenjiArai 0:5b88d5760320 271
kenjiArai 0:5b88d5760320 272 /* We can't have a match if there is no wildcard to match */
kenjiArai 0:5b88d5760320 273 if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' )
kenjiArai 0:5b88d5760320 274 return( -1 );
kenjiArai 0:5b88d5760320 275
kenjiArai 0:5b88d5760320 276 for( i = 0; i < cn_len; ++i )
kenjiArai 0:5b88d5760320 277 {
kenjiArai 0:5b88d5760320 278 if( cn[i] == '.' )
kenjiArai 0:5b88d5760320 279 {
kenjiArai 0:5b88d5760320 280 cn_idx = i;
kenjiArai 0:5b88d5760320 281 break;
kenjiArai 0:5b88d5760320 282 }
kenjiArai 0:5b88d5760320 283 }
kenjiArai 0:5b88d5760320 284
kenjiArai 0:5b88d5760320 285 if( cn_idx == 0 )
kenjiArai 0:5b88d5760320 286 return( -1 );
kenjiArai 0:5b88d5760320 287
kenjiArai 0:5b88d5760320 288 if( cn_len - cn_idx == name->len - 1 &&
kenjiArai 0:5b88d5760320 289 x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 )
kenjiArai 0:5b88d5760320 290 {
kenjiArai 0:5b88d5760320 291 return( 0 );
kenjiArai 0:5b88d5760320 292 }
kenjiArai 0:5b88d5760320 293
kenjiArai 0:5b88d5760320 294 return( -1 );
kenjiArai 0:5b88d5760320 295 }
kenjiArai 0:5b88d5760320 296
kenjiArai 0:5b88d5760320 297 /*
kenjiArai 0:5b88d5760320 298 * Compare two X.509 strings, case-insensitive, and allowing for some encoding
kenjiArai 0:5b88d5760320 299 * variations (but not all).
kenjiArai 0:5b88d5760320 300 *
kenjiArai 0:5b88d5760320 301 * Return 0 if equal, -1 otherwise.
kenjiArai 0:5b88d5760320 302 */
kenjiArai 0:5b88d5760320 303 static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b )
kenjiArai 0:5b88d5760320 304 {
kenjiArai 0:5b88d5760320 305 if( a->tag == b->tag &&
kenjiArai 0:5b88d5760320 306 a->len == b->len &&
kenjiArai 0:5b88d5760320 307 memcmp( a->p, b->p, b->len ) == 0 )
kenjiArai 0:5b88d5760320 308 {
kenjiArai 0:5b88d5760320 309 return( 0 );
kenjiArai 0:5b88d5760320 310 }
kenjiArai 0:5b88d5760320 311
kenjiArai 0:5b88d5760320 312 if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
kenjiArai 0:5b88d5760320 313 ( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
kenjiArai 0:5b88d5760320 314 a->len == b->len &&
kenjiArai 0:5b88d5760320 315 x509_memcasecmp( a->p, b->p, b->len ) == 0 )
kenjiArai 0:5b88d5760320 316 {
kenjiArai 0:5b88d5760320 317 return( 0 );
kenjiArai 0:5b88d5760320 318 }
kenjiArai 0:5b88d5760320 319
kenjiArai 0:5b88d5760320 320 return( -1 );
kenjiArai 0:5b88d5760320 321 }
kenjiArai 0:5b88d5760320 322
kenjiArai 0:5b88d5760320 323 /*
kenjiArai 0:5b88d5760320 324 * Compare two X.509 Names (aka rdnSequence).
kenjiArai 0:5b88d5760320 325 *
kenjiArai 0:5b88d5760320 326 * See RFC 5280 section 7.1, though we don't implement the whole algorithm:
kenjiArai 0:5b88d5760320 327 * we sometimes return unequal when the full algorithm would return equal,
kenjiArai 0:5b88d5760320 328 * but never the other way. (In particular, we don't do Unicode normalisation
kenjiArai 0:5b88d5760320 329 * or space folding.)
kenjiArai 0:5b88d5760320 330 *
kenjiArai 0:5b88d5760320 331 * Return 0 if equal, -1 otherwise.
kenjiArai 0:5b88d5760320 332 */
kenjiArai 0:5b88d5760320 333 static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b )
kenjiArai 0:5b88d5760320 334 {
kenjiArai 0:5b88d5760320 335 /* Avoid recursion, it might not be optimised by the compiler */
kenjiArai 0:5b88d5760320 336 while( a != NULL || b != NULL )
kenjiArai 0:5b88d5760320 337 {
kenjiArai 0:5b88d5760320 338 if( a == NULL || b == NULL )
kenjiArai 0:5b88d5760320 339 return( -1 );
kenjiArai 0:5b88d5760320 340
kenjiArai 0:5b88d5760320 341 /* type */
kenjiArai 0:5b88d5760320 342 if( a->oid.tag != b->oid.tag ||
kenjiArai 0:5b88d5760320 343 a->oid.len != b->oid.len ||
kenjiArai 0:5b88d5760320 344 memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 )
kenjiArai 0:5b88d5760320 345 {
kenjiArai 0:5b88d5760320 346 return( -1 );
kenjiArai 0:5b88d5760320 347 }
kenjiArai 0:5b88d5760320 348
kenjiArai 0:5b88d5760320 349 /* value */
kenjiArai 0:5b88d5760320 350 if( x509_string_cmp( &a->val, &b->val ) != 0 )
kenjiArai 0:5b88d5760320 351 return( -1 );
kenjiArai 0:5b88d5760320 352
kenjiArai 0:5b88d5760320 353 /* structure of the list of sets */
kenjiArai 0:5b88d5760320 354 if( a->next_merged != b->next_merged )
kenjiArai 0:5b88d5760320 355 return( -1 );
kenjiArai 0:5b88d5760320 356
kenjiArai 0:5b88d5760320 357 a = a->next;
kenjiArai 0:5b88d5760320 358 b = b->next;
kenjiArai 0:5b88d5760320 359 }
kenjiArai 0:5b88d5760320 360
kenjiArai 0:5b88d5760320 361 /* a == NULL == b */
kenjiArai 0:5b88d5760320 362 return( 0 );
kenjiArai 0:5b88d5760320 363 }
kenjiArai 0:5b88d5760320 364
kenjiArai 0:5b88d5760320 365 /*
kenjiArai 0:5b88d5760320 366 * Reset (init or clear) a verify_chain
kenjiArai 0:5b88d5760320 367 */
kenjiArai 0:5b88d5760320 368 static void x509_crt_verify_chain_reset(
kenjiArai 0:5b88d5760320 369 mbedtls_x509_crt_verify_chain *ver_chain )
kenjiArai 0:5b88d5760320 370 {
kenjiArai 0:5b88d5760320 371 size_t i;
kenjiArai 0:5b88d5760320 372
kenjiArai 0:5b88d5760320 373 for( i = 0; i < MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE; i++ )
kenjiArai 0:5b88d5760320 374 {
kenjiArai 0:5b88d5760320 375 ver_chain->items[i].crt = NULL;
kenjiArai 0:5b88d5760320 376 ver_chain->items[i].flags = (uint32_t) -1;
kenjiArai 0:5b88d5760320 377 }
kenjiArai 0:5b88d5760320 378
kenjiArai 0:5b88d5760320 379 ver_chain->len = 0;
kenjiArai 0:5b88d5760320 380
kenjiArai 0:5b88d5760320 381 #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
kenjiArai 0:5b88d5760320 382 ver_chain->trust_ca_cb_result = NULL;
kenjiArai 0:5b88d5760320 383 #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
kenjiArai 0:5b88d5760320 384 }
kenjiArai 0:5b88d5760320 385
kenjiArai 0:5b88d5760320 386 /*
kenjiArai 0:5b88d5760320 387 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
kenjiArai 0:5b88d5760320 388 */
kenjiArai 0:5b88d5760320 389 static int x509_get_version( unsigned char **p,
kenjiArai 0:5b88d5760320 390 const unsigned char *end,
kenjiArai 0:5b88d5760320 391 int *ver )
kenjiArai 0:5b88d5760320 392 {
kenjiArai 0:5b88d5760320 393 int ret;
kenjiArai 0:5b88d5760320 394 size_t len;
kenjiArai 0:5b88d5760320 395
kenjiArai 0:5b88d5760320 396 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
kenjiArai 0:5b88d5760320 397 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) != 0 )
kenjiArai 0:5b88d5760320 398 {
kenjiArai 0:5b88d5760320 399 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
kenjiArai 0:5b88d5760320 400 {
kenjiArai 0:5b88d5760320 401 *ver = 0;
kenjiArai 0:5b88d5760320 402 return( 0 );
kenjiArai 0:5b88d5760320 403 }
kenjiArai 0:5b88d5760320 404
kenjiArai 0:5b88d5760320 405 return( ret );
kenjiArai 0:5b88d5760320 406 }
kenjiArai 0:5b88d5760320 407
kenjiArai 0:5b88d5760320 408 end = *p + len;
kenjiArai 0:5b88d5760320 409
kenjiArai 0:5b88d5760320 410 if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 )
kenjiArai 0:5b88d5760320 411 return( MBEDTLS_ERR_X509_INVALID_VERSION + ret );
kenjiArai 0:5b88d5760320 412
kenjiArai 0:5b88d5760320 413 if( *p != end )
kenjiArai 0:5b88d5760320 414 return( MBEDTLS_ERR_X509_INVALID_VERSION +
kenjiArai 0:5b88d5760320 415 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kenjiArai 0:5b88d5760320 416
kenjiArai 0:5b88d5760320 417 return( 0 );
kenjiArai 0:5b88d5760320 418 }
kenjiArai 0:5b88d5760320 419
kenjiArai 0:5b88d5760320 420 /*
kenjiArai 0:5b88d5760320 421 * Validity ::= SEQUENCE {
kenjiArai 0:5b88d5760320 422 * notBefore Time,
kenjiArai 0:5b88d5760320 423 * notAfter Time }
kenjiArai 0:5b88d5760320 424 */
kenjiArai 0:5b88d5760320 425 static int x509_get_dates( unsigned char **p,
kenjiArai 0:5b88d5760320 426 const unsigned char *end,
kenjiArai 0:5b88d5760320 427 mbedtls_x509_time *from,
kenjiArai 0:5b88d5760320 428 mbedtls_x509_time *to )
kenjiArai 0:5b88d5760320 429 {
kenjiArai 0:5b88d5760320 430 int ret;
kenjiArai 0:5b88d5760320 431 size_t len;
kenjiArai 0:5b88d5760320 432
kenjiArai 0:5b88d5760320 433 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
kenjiArai 0:5b88d5760320 434 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
kenjiArai 0:5b88d5760320 435 return( MBEDTLS_ERR_X509_INVALID_DATE + ret );
kenjiArai 0:5b88d5760320 436
kenjiArai 0:5b88d5760320 437 end = *p + len;
kenjiArai 0:5b88d5760320 438
kenjiArai 0:5b88d5760320 439 if( ( ret = mbedtls_x509_get_time( p, end, from ) ) != 0 )
kenjiArai 0:5b88d5760320 440 return( ret );
kenjiArai 0:5b88d5760320 441
kenjiArai 0:5b88d5760320 442 if( ( ret = mbedtls_x509_get_time( p, end, to ) ) != 0 )
kenjiArai 0:5b88d5760320 443 return( ret );
kenjiArai 0:5b88d5760320 444
kenjiArai 0:5b88d5760320 445 if( *p != end )
kenjiArai 0:5b88d5760320 446 return( MBEDTLS_ERR_X509_INVALID_DATE +
kenjiArai 0:5b88d5760320 447 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kenjiArai 0:5b88d5760320 448
kenjiArai 0:5b88d5760320 449 return( 0 );
kenjiArai 0:5b88d5760320 450 }
kenjiArai 0:5b88d5760320 451
kenjiArai 0:5b88d5760320 452 /*
kenjiArai 0:5b88d5760320 453 * X.509 v2/v3 unique identifier (not parsed)
kenjiArai 0:5b88d5760320 454 */
kenjiArai 0:5b88d5760320 455 static int x509_get_uid( unsigned char **p,
kenjiArai 0:5b88d5760320 456 const unsigned char *end,
kenjiArai 0:5b88d5760320 457 mbedtls_x509_buf *uid, int n )
kenjiArai 0:5b88d5760320 458 {
kenjiArai 0:5b88d5760320 459 int ret;
kenjiArai 0:5b88d5760320 460
kenjiArai 0:5b88d5760320 461 if( *p == end )
kenjiArai 0:5b88d5760320 462 return( 0 );
kenjiArai 0:5b88d5760320 463
kenjiArai 0:5b88d5760320 464 uid->tag = **p;
kenjiArai 0:5b88d5760320 465
kenjiArai 0:5b88d5760320 466 if( ( ret = mbedtls_asn1_get_tag( p, end, &uid->len,
kenjiArai 0:5b88d5760320 467 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | n ) ) != 0 )
kenjiArai 0:5b88d5760320 468 {
kenjiArai 0:5b88d5760320 469 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
kenjiArai 0:5b88d5760320 470 return( 0 );
kenjiArai 0:5b88d5760320 471
kenjiArai 0:5b88d5760320 472 return( ret );
kenjiArai 0:5b88d5760320 473 }
kenjiArai 0:5b88d5760320 474
kenjiArai 0:5b88d5760320 475 uid->p = *p;
kenjiArai 0:5b88d5760320 476 *p += uid->len;
kenjiArai 0:5b88d5760320 477
kenjiArai 0:5b88d5760320 478 return( 0 );
kenjiArai 0:5b88d5760320 479 }
kenjiArai 0:5b88d5760320 480
kenjiArai 0:5b88d5760320 481 static int x509_get_basic_constraints( unsigned char **p,
kenjiArai 0:5b88d5760320 482 const unsigned char *end,
kenjiArai 0:5b88d5760320 483 int *ca_istrue,
kenjiArai 0:5b88d5760320 484 int *max_pathlen )
kenjiArai 0:5b88d5760320 485 {
kenjiArai 0:5b88d5760320 486 int ret;
kenjiArai 0:5b88d5760320 487 size_t len;
kenjiArai 0:5b88d5760320 488
kenjiArai 0:5b88d5760320 489 /*
kenjiArai 0:5b88d5760320 490 * BasicConstraints ::= SEQUENCE {
kenjiArai 0:5b88d5760320 491 * cA BOOLEAN DEFAULT FALSE,
kenjiArai 0:5b88d5760320 492 * pathLenConstraint INTEGER (0..MAX) OPTIONAL }
kenjiArai 0:5b88d5760320 493 */
kenjiArai 0:5b88d5760320 494 *ca_istrue = 0; /* DEFAULT FALSE */
kenjiArai 0:5b88d5760320 495 *max_pathlen = 0; /* endless */
kenjiArai 0:5b88d5760320 496
kenjiArai 0:5b88d5760320 497 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
kenjiArai 0:5b88d5760320 498 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
kenjiArai 0:5b88d5760320 499 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kenjiArai 0:5b88d5760320 500
kenjiArai 0:5b88d5760320 501 if( *p == end )
kenjiArai 0:5b88d5760320 502 return( 0 );
kenjiArai 0:5b88d5760320 503
kenjiArai 0:5b88d5760320 504 if( ( ret = mbedtls_asn1_get_bool( p, end, ca_istrue ) ) != 0 )
kenjiArai 0:5b88d5760320 505 {
kenjiArai 0:5b88d5760320 506 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
kenjiArai 0:5b88d5760320 507 ret = mbedtls_asn1_get_int( p, end, ca_istrue );
kenjiArai 0:5b88d5760320 508
kenjiArai 0:5b88d5760320 509 if( ret != 0 )
kenjiArai 0:5b88d5760320 510 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kenjiArai 0:5b88d5760320 511
kenjiArai 0:5b88d5760320 512 if( *ca_istrue != 0 )
kenjiArai 0:5b88d5760320 513 *ca_istrue = 1;
kenjiArai 0:5b88d5760320 514 }
kenjiArai 0:5b88d5760320 515
kenjiArai 0:5b88d5760320 516 if( *p == end )
kenjiArai 0:5b88d5760320 517 return( 0 );
kenjiArai 0:5b88d5760320 518
kenjiArai 0:5b88d5760320 519 if( ( ret = mbedtls_asn1_get_int( p, end, max_pathlen ) ) != 0 )
kenjiArai 0:5b88d5760320 520 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kenjiArai 0:5b88d5760320 521
kenjiArai 0:5b88d5760320 522 if( *p != end )
kenjiArai 0:5b88d5760320 523 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kenjiArai 0:5b88d5760320 524 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kenjiArai 0:5b88d5760320 525
kenjiArai 0:5b88d5760320 526 (*max_pathlen)++;
kenjiArai 0:5b88d5760320 527
kenjiArai 0:5b88d5760320 528 return( 0 );
kenjiArai 0:5b88d5760320 529 }
kenjiArai 0:5b88d5760320 530
kenjiArai 0:5b88d5760320 531 static int x509_get_ns_cert_type( unsigned char **p,
kenjiArai 0:5b88d5760320 532 const unsigned char *end,
kenjiArai 0:5b88d5760320 533 unsigned char *ns_cert_type)
kenjiArai 0:5b88d5760320 534 {
kenjiArai 0:5b88d5760320 535 int ret;
kenjiArai 0:5b88d5760320 536 mbedtls_x509_bitstring bs = { 0, 0, NULL };
kenjiArai 0:5b88d5760320 537
kenjiArai 0:5b88d5760320 538 if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 )
kenjiArai 0:5b88d5760320 539 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kenjiArai 0:5b88d5760320 540
kenjiArai 0:5b88d5760320 541 if( bs.len != 1 )
kenjiArai 0:5b88d5760320 542 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kenjiArai 0:5b88d5760320 543 MBEDTLS_ERR_ASN1_INVALID_LENGTH );
kenjiArai 0:5b88d5760320 544
kenjiArai 0:5b88d5760320 545 /* Get actual bitstring */
kenjiArai 0:5b88d5760320 546 *ns_cert_type = *bs.p;
kenjiArai 0:5b88d5760320 547 return( 0 );
kenjiArai 0:5b88d5760320 548 }
kenjiArai 0:5b88d5760320 549
kenjiArai 0:5b88d5760320 550 static int x509_get_key_usage( unsigned char **p,
kenjiArai 0:5b88d5760320 551 const unsigned char *end,
kenjiArai 0:5b88d5760320 552 unsigned int *key_usage)
kenjiArai 0:5b88d5760320 553 {
kenjiArai 0:5b88d5760320 554 int ret;
kenjiArai 0:5b88d5760320 555 size_t i;
kenjiArai 0:5b88d5760320 556 mbedtls_x509_bitstring bs = { 0, 0, NULL };
kenjiArai 0:5b88d5760320 557
kenjiArai 0:5b88d5760320 558 if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 )
kenjiArai 0:5b88d5760320 559 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kenjiArai 0:5b88d5760320 560
kenjiArai 0:5b88d5760320 561 if( bs.len < 1 )
kenjiArai 0:5b88d5760320 562 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kenjiArai 0:5b88d5760320 563 MBEDTLS_ERR_ASN1_INVALID_LENGTH );
kenjiArai 0:5b88d5760320 564
kenjiArai 0:5b88d5760320 565 /* Get actual bitstring */
kenjiArai 0:5b88d5760320 566 *key_usage = 0;
kenjiArai 0:5b88d5760320 567 for( i = 0; i < bs.len && i < sizeof( unsigned int ); i++ )
kenjiArai 0:5b88d5760320 568 {
kenjiArai 0:5b88d5760320 569 *key_usage |= (unsigned int) bs.p[i] << (8*i);
kenjiArai 0:5b88d5760320 570 }
kenjiArai 0:5b88d5760320 571
kenjiArai 0:5b88d5760320 572 return( 0 );
kenjiArai 0:5b88d5760320 573 }
kenjiArai 0:5b88d5760320 574
kenjiArai 0:5b88d5760320 575 /*
kenjiArai 0:5b88d5760320 576 * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
kenjiArai 0:5b88d5760320 577 *
kenjiArai 0:5b88d5760320 578 * KeyPurposeId ::= OBJECT IDENTIFIER
kenjiArai 0:5b88d5760320 579 */
kenjiArai 0:5b88d5760320 580 static int x509_get_ext_key_usage( unsigned char **p,
kenjiArai 0:5b88d5760320 581 const unsigned char *end,
kenjiArai 0:5b88d5760320 582 mbedtls_x509_sequence *ext_key_usage)
kenjiArai 0:5b88d5760320 583 {
kenjiArai 0:5b88d5760320 584 int ret;
kenjiArai 0:5b88d5760320 585
kenjiArai 0:5b88d5760320 586 if( ( ret = mbedtls_asn1_get_sequence_of( p, end, ext_key_usage, MBEDTLS_ASN1_OID ) ) != 0 )
kenjiArai 0:5b88d5760320 587 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kenjiArai 0:5b88d5760320 588
kenjiArai 0:5b88d5760320 589 /* Sequence length must be >= 1 */
kenjiArai 0:5b88d5760320 590 if( ext_key_usage->buf.p == NULL )
kenjiArai 0:5b88d5760320 591 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kenjiArai 0:5b88d5760320 592 MBEDTLS_ERR_ASN1_INVALID_LENGTH );
kenjiArai 0:5b88d5760320 593
kenjiArai 0:5b88d5760320 594 return( 0 );
kenjiArai 0:5b88d5760320 595 }
kenjiArai 0:5b88d5760320 596
kenjiArai 0:5b88d5760320 597 /*
kenjiArai 0:5b88d5760320 598 * SubjectAltName ::= GeneralNames
kenjiArai 0:5b88d5760320 599 *
kenjiArai 0:5b88d5760320 600 * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
kenjiArai 0:5b88d5760320 601 *
kenjiArai 0:5b88d5760320 602 * GeneralName ::= CHOICE {
kenjiArai 0:5b88d5760320 603 * otherName [0] OtherName,
kenjiArai 0:5b88d5760320 604 * rfc822Name [1] IA5String,
kenjiArai 0:5b88d5760320 605 * dNSName [2] IA5String,
kenjiArai 0:5b88d5760320 606 * x400Address [3] ORAddress,
kenjiArai 0:5b88d5760320 607 * directoryName [4] Name,
kenjiArai 0:5b88d5760320 608 * ediPartyName [5] EDIPartyName,
kenjiArai 0:5b88d5760320 609 * uniformResourceIdentifier [6] IA5String,
kenjiArai 0:5b88d5760320 610 * iPAddress [7] OCTET STRING,
kenjiArai 0:5b88d5760320 611 * registeredID [8] OBJECT IDENTIFIER }
kenjiArai 0:5b88d5760320 612 *
kenjiArai 0:5b88d5760320 613 * OtherName ::= SEQUENCE {
kenjiArai 0:5b88d5760320 614 * type-id OBJECT IDENTIFIER,
kenjiArai 0:5b88d5760320 615 * value [0] EXPLICIT ANY DEFINED BY type-id }
kenjiArai 0:5b88d5760320 616 *
kenjiArai 0:5b88d5760320 617 * EDIPartyName ::= SEQUENCE {
kenjiArai 0:5b88d5760320 618 * nameAssigner [0] DirectoryString OPTIONAL,
kenjiArai 0:5b88d5760320 619 * partyName [1] DirectoryString }
kenjiArai 0:5b88d5760320 620 *
kenjiArai 0:5b88d5760320 621 * NOTE: we list all types, but only use dNSName and otherName
kenjiArai 0:5b88d5760320 622 * of type HwModuleName, as defined in RFC 4108, at this point.
kenjiArai 0:5b88d5760320 623 */
kenjiArai 0:5b88d5760320 624 static int x509_get_subject_alt_name( unsigned char **p,
kenjiArai 0:5b88d5760320 625 const unsigned char *end,
kenjiArai 0:5b88d5760320 626 mbedtls_x509_sequence *subject_alt_name )
kenjiArai 0:5b88d5760320 627 {
kenjiArai 0:5b88d5760320 628 int ret;
kenjiArai 0:5b88d5760320 629 size_t len, tag_len;
kenjiArai 0:5b88d5760320 630 mbedtls_asn1_buf *buf;
kenjiArai 0:5b88d5760320 631 unsigned char tag;
kenjiArai 0:5b88d5760320 632 mbedtls_asn1_sequence *cur = subject_alt_name;
kenjiArai 0:5b88d5760320 633
kenjiArai 0:5b88d5760320 634 /* Get main sequence tag */
kenjiArai 0:5b88d5760320 635 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
kenjiArai 0:5b88d5760320 636 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
kenjiArai 0:5b88d5760320 637 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kenjiArai 0:5b88d5760320 638
kenjiArai 0:5b88d5760320 639 if( *p + len != end )
kenjiArai 0:5b88d5760320 640 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kenjiArai 0:5b88d5760320 641 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kenjiArai 0:5b88d5760320 642
kenjiArai 0:5b88d5760320 643 while( *p < end )
kenjiArai 0:5b88d5760320 644 {
kenjiArai 0:5b88d5760320 645 mbedtls_x509_subject_alternative_name dummy_san_buf;
kenjiArai 0:5b88d5760320 646 memset( &dummy_san_buf, 0, sizeof( dummy_san_buf ) );
kenjiArai 0:5b88d5760320 647
kenjiArai 0:5b88d5760320 648 if( ( end - *p ) < 1 )
kenjiArai 0:5b88d5760320 649 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kenjiArai 0:5b88d5760320 650 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
kenjiArai 0:5b88d5760320 651
kenjiArai 0:5b88d5760320 652 tag = **p;
kenjiArai 0:5b88d5760320 653 (*p)++;
kenjiArai 0:5b88d5760320 654 if( ( ret = mbedtls_asn1_get_len( p, end, &tag_len ) ) != 0 )
kenjiArai 0:5b88d5760320 655 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kenjiArai 0:5b88d5760320 656
kenjiArai 0:5b88d5760320 657 if( ( tag & MBEDTLS_ASN1_TAG_CLASS_MASK ) !=
kenjiArai 0:5b88d5760320 658 MBEDTLS_ASN1_CONTEXT_SPECIFIC )
kenjiArai 0:5b88d5760320 659 {
kenjiArai 0:5b88d5760320 660 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kenjiArai 0:5b88d5760320 661 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
kenjiArai 0:5b88d5760320 662 }
kenjiArai 0:5b88d5760320 663
kenjiArai 0:5b88d5760320 664 /*
kenjiArai 0:5b88d5760320 665 * Check that the SAN are structured correct.
kenjiArai 0:5b88d5760320 666 */
kenjiArai 0:5b88d5760320 667 ret = mbedtls_x509_parse_subject_alt_name( &(cur->buf), &dummy_san_buf );
kenjiArai 0:5b88d5760320 668 /*
kenjiArai 0:5b88d5760320 669 * In case the extension is malformed, return an error,
kenjiArai 0:5b88d5760320 670 * and clear the allocated sequences.
kenjiArai 0:5b88d5760320 671 */
kenjiArai 0:5b88d5760320 672 if( ret != 0 && ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE )
kenjiArai 0:5b88d5760320 673 {
kenjiArai 0:5b88d5760320 674 mbedtls_x509_sequence *seq_cur = subject_alt_name->next;
kenjiArai 0:5b88d5760320 675 mbedtls_x509_sequence *seq_prv;
kenjiArai 0:5b88d5760320 676 while( seq_cur != NULL )
kenjiArai 0:5b88d5760320 677 {
kenjiArai 0:5b88d5760320 678 seq_prv = seq_cur;
kenjiArai 0:5b88d5760320 679 seq_cur = seq_cur->next;
kenjiArai 0:5b88d5760320 680 mbedtls_platform_zeroize( seq_prv,
kenjiArai 0:5b88d5760320 681 sizeof( mbedtls_x509_sequence ) );
kenjiArai 0:5b88d5760320 682 mbedtls_free( seq_prv );
kenjiArai 0:5b88d5760320 683 }
kenjiArai 0:5b88d5760320 684 subject_alt_name->next = NULL;
kenjiArai 0:5b88d5760320 685 return( ret );
kenjiArai 0:5b88d5760320 686 }
kenjiArai 0:5b88d5760320 687
kenjiArai 0:5b88d5760320 688 /* Allocate and assign next pointer */
kenjiArai 0:5b88d5760320 689 if( cur->buf.p != NULL )
kenjiArai 0:5b88d5760320 690 {
kenjiArai 0:5b88d5760320 691 if( cur->next != NULL )
kenjiArai 0:5b88d5760320 692 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS );
kenjiArai 0:5b88d5760320 693
kenjiArai 0:5b88d5760320 694 cur->next = mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) );
kenjiArai 0:5b88d5760320 695
kenjiArai 0:5b88d5760320 696 if( cur->next == NULL )
kenjiArai 0:5b88d5760320 697 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kenjiArai 0:5b88d5760320 698 MBEDTLS_ERR_ASN1_ALLOC_FAILED );
kenjiArai 0:5b88d5760320 699
kenjiArai 0:5b88d5760320 700 cur = cur->next;
kenjiArai 0:5b88d5760320 701 }
kenjiArai 0:5b88d5760320 702
kenjiArai 0:5b88d5760320 703 buf = &(cur->buf);
kenjiArai 0:5b88d5760320 704 buf->tag = tag;
kenjiArai 0:5b88d5760320 705 buf->p = *p;
kenjiArai 0:5b88d5760320 706 buf->len = tag_len;
kenjiArai 0:5b88d5760320 707 *p += buf->len;
kenjiArai 0:5b88d5760320 708 }
kenjiArai 0:5b88d5760320 709
kenjiArai 0:5b88d5760320 710 /* Set final sequence entry's next pointer to NULL */
kenjiArai 0:5b88d5760320 711 cur->next = NULL;
kenjiArai 0:5b88d5760320 712
kenjiArai 0:5b88d5760320 713 if( *p != end )
kenjiArai 0:5b88d5760320 714 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kenjiArai 0:5b88d5760320 715 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kenjiArai 0:5b88d5760320 716
kenjiArai 0:5b88d5760320 717 return( 0 );
kenjiArai 0:5b88d5760320 718 }
kenjiArai 0:5b88d5760320 719
kenjiArai 0:5b88d5760320 720 /*
kenjiArai 0:5b88d5760320 721 * id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 }
kenjiArai 0:5b88d5760320 722 *
kenjiArai 0:5b88d5760320 723 * anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 }
kenjiArai 0:5b88d5760320 724 *
kenjiArai 0:5b88d5760320 725 * certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
kenjiArai 0:5b88d5760320 726 *
kenjiArai 0:5b88d5760320 727 * PolicyInformation ::= SEQUENCE {
kenjiArai 0:5b88d5760320 728 * policyIdentifier CertPolicyId,
kenjiArai 0:5b88d5760320 729 * policyQualifiers SEQUENCE SIZE (1..MAX) OF
kenjiArai 0:5b88d5760320 730 * PolicyQualifierInfo OPTIONAL }
kenjiArai 0:5b88d5760320 731 *
kenjiArai 0:5b88d5760320 732 * CertPolicyId ::= OBJECT IDENTIFIER
kenjiArai 0:5b88d5760320 733 *
kenjiArai 0:5b88d5760320 734 * PolicyQualifierInfo ::= SEQUENCE {
kenjiArai 0:5b88d5760320 735 * policyQualifierId PolicyQualifierId,
kenjiArai 0:5b88d5760320 736 * qualifier ANY DEFINED BY policyQualifierId }
kenjiArai 0:5b88d5760320 737 *
kenjiArai 0:5b88d5760320 738 * -- policyQualifierIds for Internet policy qualifiers
kenjiArai 0:5b88d5760320 739 *
kenjiArai 0:5b88d5760320 740 * id-qt OBJECT IDENTIFIER ::= { id-pkix 2 }
kenjiArai 0:5b88d5760320 741 * id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 }
kenjiArai 0:5b88d5760320 742 * id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 }
kenjiArai 0:5b88d5760320 743 *
kenjiArai 0:5b88d5760320 744 * PolicyQualifierId ::= OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice )
kenjiArai 0:5b88d5760320 745 *
kenjiArai 0:5b88d5760320 746 * Qualifier ::= CHOICE {
kenjiArai 0:5b88d5760320 747 * cPSuri CPSuri,
kenjiArai 0:5b88d5760320 748 * userNotice UserNotice }
kenjiArai 0:5b88d5760320 749 *
kenjiArai 0:5b88d5760320 750 * CPSuri ::= IA5String
kenjiArai 0:5b88d5760320 751 *
kenjiArai 0:5b88d5760320 752 * UserNotice ::= SEQUENCE {
kenjiArai 0:5b88d5760320 753 * noticeRef NoticeReference OPTIONAL,
kenjiArai 0:5b88d5760320 754 * explicitText DisplayText OPTIONAL }
kenjiArai 0:5b88d5760320 755 *
kenjiArai 0:5b88d5760320 756 * NoticeReference ::= SEQUENCE {
kenjiArai 0:5b88d5760320 757 * organization DisplayText,
kenjiArai 0:5b88d5760320 758 * noticeNumbers SEQUENCE OF INTEGER }
kenjiArai 0:5b88d5760320 759 *
kenjiArai 0:5b88d5760320 760 * DisplayText ::= CHOICE {
kenjiArai 0:5b88d5760320 761 * ia5String IA5String (SIZE (1..200)),
kenjiArai 0:5b88d5760320 762 * visibleString VisibleString (SIZE (1..200)),
kenjiArai 0:5b88d5760320 763 * bmpString BMPString (SIZE (1..200)),
kenjiArai 0:5b88d5760320 764 * utf8String UTF8String (SIZE (1..200)) }
kenjiArai 0:5b88d5760320 765 *
kenjiArai 0:5b88d5760320 766 * NOTE: we only parse and use anyPolicy without qualifiers at this point
kenjiArai 0:5b88d5760320 767 * as defined in RFC 5280.
kenjiArai 0:5b88d5760320 768 */
kenjiArai 0:5b88d5760320 769 static int x509_get_certificate_policies( unsigned char **p,
kenjiArai 0:5b88d5760320 770 const unsigned char *end,
kenjiArai 0:5b88d5760320 771 mbedtls_x509_sequence *certificate_policies )
kenjiArai 0:5b88d5760320 772 {
kenjiArai 0:5b88d5760320 773 int ret, parse_ret = 0;
kenjiArai 0:5b88d5760320 774 size_t len;
kenjiArai 0:5b88d5760320 775 mbedtls_asn1_buf *buf;
kenjiArai 0:5b88d5760320 776 mbedtls_asn1_sequence *cur = certificate_policies;
kenjiArai 0:5b88d5760320 777
kenjiArai 0:5b88d5760320 778 /* Get main sequence tag */
kenjiArai 0:5b88d5760320 779 ret = mbedtls_asn1_get_tag( p, end, &len,
kenjiArai 0:5b88d5760320 780 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
kenjiArai 0:5b88d5760320 781 if( ret != 0 )
kenjiArai 0:5b88d5760320 782 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kenjiArai 0:5b88d5760320 783
kenjiArai 0:5b88d5760320 784 if( *p + len != end )
kenjiArai 0:5b88d5760320 785 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kenjiArai 0:5b88d5760320 786 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kenjiArai 0:5b88d5760320 787
kenjiArai 0:5b88d5760320 788 /*
kenjiArai 0:5b88d5760320 789 * Cannot be an empty sequence.
kenjiArai 0:5b88d5760320 790 */
kenjiArai 0:5b88d5760320 791 if( len == 0 )
kenjiArai 0:5b88d5760320 792 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kenjiArai 0:5b88d5760320 793 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kenjiArai 0:5b88d5760320 794
kenjiArai 0:5b88d5760320 795 while( *p < end )
kenjiArai 0:5b88d5760320 796 {
kenjiArai 0:5b88d5760320 797 mbedtls_x509_buf policy_oid;
kenjiArai 0:5b88d5760320 798 const unsigned char *policy_end;
kenjiArai 0:5b88d5760320 799
kenjiArai 0:5b88d5760320 800 /*
kenjiArai 0:5b88d5760320 801 * Get the policy sequence
kenjiArai 0:5b88d5760320 802 */
kenjiArai 0:5b88d5760320 803 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
kenjiArai 0:5b88d5760320 804 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
kenjiArai 0:5b88d5760320 805 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kenjiArai 0:5b88d5760320 806
kenjiArai 0:5b88d5760320 807 policy_end = *p + len;
kenjiArai 0:5b88d5760320 808
kenjiArai 0:5b88d5760320 809 if( ( ret = mbedtls_asn1_get_tag( p, policy_end, &len,
kenjiArai 0:5b88d5760320 810 MBEDTLS_ASN1_OID ) ) != 0 )
kenjiArai 0:5b88d5760320 811 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kenjiArai 0:5b88d5760320 812
kenjiArai 0:5b88d5760320 813 policy_oid.tag = MBEDTLS_ASN1_OID;
kenjiArai 0:5b88d5760320 814 policy_oid.len = len;
kenjiArai 0:5b88d5760320 815 policy_oid.p = *p;
kenjiArai 0:5b88d5760320 816
kenjiArai 0:5b88d5760320 817 /*
kenjiArai 0:5b88d5760320 818 * Only AnyPolicy is currently supported when enforcing policy.
kenjiArai 0:5b88d5760320 819 */
kenjiArai 0:5b88d5760320 820 if( MBEDTLS_OID_CMP( MBEDTLS_OID_ANY_POLICY, &policy_oid ) != 0 )
kenjiArai 0:5b88d5760320 821 {
kenjiArai 0:5b88d5760320 822 /*
kenjiArai 0:5b88d5760320 823 * Set the parsing return code but continue parsing, in case this
kenjiArai 0:5b88d5760320 824 * extension is critical and MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
kenjiArai 0:5b88d5760320 825 * is configured.
kenjiArai 0:5b88d5760320 826 */
kenjiArai 0:5b88d5760320 827 parse_ret = MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
kenjiArai 0:5b88d5760320 828 }
kenjiArai 0:5b88d5760320 829
kenjiArai 0:5b88d5760320 830 /* Allocate and assign next pointer */
kenjiArai 0:5b88d5760320 831 if( cur->buf.p != NULL )
kenjiArai 0:5b88d5760320 832 {
kenjiArai 0:5b88d5760320 833 if( cur->next != NULL )
kenjiArai 0:5b88d5760320 834 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS );
kenjiArai 0:5b88d5760320 835
kenjiArai 0:5b88d5760320 836 cur->next = mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) );
kenjiArai 0:5b88d5760320 837
kenjiArai 0:5b88d5760320 838 if( cur->next == NULL )
kenjiArai 0:5b88d5760320 839 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kenjiArai 0:5b88d5760320 840 MBEDTLS_ERR_ASN1_ALLOC_FAILED );
kenjiArai 0:5b88d5760320 841
kenjiArai 0:5b88d5760320 842 cur = cur->next;
kenjiArai 0:5b88d5760320 843 }
kenjiArai 0:5b88d5760320 844
kenjiArai 0:5b88d5760320 845 buf = &( cur->buf );
kenjiArai 0:5b88d5760320 846 buf->tag = policy_oid.tag;
kenjiArai 0:5b88d5760320 847 buf->p = policy_oid.p;
kenjiArai 0:5b88d5760320 848 buf->len = policy_oid.len;
kenjiArai 0:5b88d5760320 849
kenjiArai 0:5b88d5760320 850 *p += len;
kenjiArai 0:5b88d5760320 851
kenjiArai 0:5b88d5760320 852 /*
kenjiArai 0:5b88d5760320 853 * If there is an optional qualifier, then *p < policy_end
kenjiArai 0:5b88d5760320 854 * Check the Qualifier len to verify it doesn't exceed policy_end.
kenjiArai 0:5b88d5760320 855 */
kenjiArai 0:5b88d5760320 856 if( *p < policy_end )
kenjiArai 0:5b88d5760320 857 {
kenjiArai 0:5b88d5760320 858 if( ( ret = mbedtls_asn1_get_tag( p, policy_end, &len,
kenjiArai 0:5b88d5760320 859 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
kenjiArai 0:5b88d5760320 860 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kenjiArai 0:5b88d5760320 861 /*
kenjiArai 0:5b88d5760320 862 * Skip the optional policy qualifiers.
kenjiArai 0:5b88d5760320 863 */
kenjiArai 0:5b88d5760320 864 *p += len;
kenjiArai 0:5b88d5760320 865 }
kenjiArai 0:5b88d5760320 866
kenjiArai 0:5b88d5760320 867 if( *p != policy_end )
kenjiArai 0:5b88d5760320 868 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kenjiArai 0:5b88d5760320 869 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kenjiArai 0:5b88d5760320 870 }
kenjiArai 0:5b88d5760320 871
kenjiArai 0:5b88d5760320 872 /* Set final sequence entry's next pointer to NULL */
kenjiArai 0:5b88d5760320 873 cur->next = NULL;
kenjiArai 0:5b88d5760320 874
kenjiArai 0:5b88d5760320 875 if( *p != end )
kenjiArai 0:5b88d5760320 876 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kenjiArai 0:5b88d5760320 877 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kenjiArai 0:5b88d5760320 878
kenjiArai 0:5b88d5760320 879 return( parse_ret );
kenjiArai 0:5b88d5760320 880 }
kenjiArai 0:5b88d5760320 881
kenjiArai 0:5b88d5760320 882 /*
kenjiArai 0:5b88d5760320 883 * X.509 v3 extensions
kenjiArai 0:5b88d5760320 884 *
kenjiArai 0:5b88d5760320 885 */
kenjiArai 0:5b88d5760320 886 static int x509_get_crt_ext( unsigned char **p,
kenjiArai 0:5b88d5760320 887 const unsigned char *end,
kenjiArai 0:5b88d5760320 888 mbedtls_x509_crt *crt )
kenjiArai 0:5b88d5760320 889 {
kenjiArai 0:5b88d5760320 890 int ret;
kenjiArai 0:5b88d5760320 891 size_t len;
kenjiArai 0:5b88d5760320 892 unsigned char *end_ext_data, *end_ext_octet;
kenjiArai 0:5b88d5760320 893
kenjiArai 0:5b88d5760320 894 if( ( ret = mbedtls_x509_get_ext( p, end, &crt->v3_ext, 3 ) ) != 0 )
kenjiArai 0:5b88d5760320 895 {
kenjiArai 0:5b88d5760320 896 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
kenjiArai 0:5b88d5760320 897 return( 0 );
kenjiArai 0:5b88d5760320 898
kenjiArai 0:5b88d5760320 899 return( ret );
kenjiArai 0:5b88d5760320 900 }
kenjiArai 0:5b88d5760320 901
kenjiArai 0:5b88d5760320 902 while( *p < end )
kenjiArai 0:5b88d5760320 903 {
kenjiArai 0:5b88d5760320 904 /*
kenjiArai 0:5b88d5760320 905 * Extension ::= SEQUENCE {
kenjiArai 0:5b88d5760320 906 * extnID OBJECT IDENTIFIER,
kenjiArai 0:5b88d5760320 907 * critical BOOLEAN DEFAULT FALSE,
kenjiArai 0:5b88d5760320 908 * extnValue OCTET STRING }
kenjiArai 0:5b88d5760320 909 */
kenjiArai 0:5b88d5760320 910 mbedtls_x509_buf extn_oid = {0, 0, NULL};
kenjiArai 0:5b88d5760320 911 int is_critical = 0; /* DEFAULT FALSE */
kenjiArai 0:5b88d5760320 912 int ext_type = 0;
kenjiArai 0:5b88d5760320 913
kenjiArai 0:5b88d5760320 914 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
kenjiArai 0:5b88d5760320 915 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
kenjiArai 0:5b88d5760320 916 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kenjiArai 0:5b88d5760320 917
kenjiArai 0:5b88d5760320 918 end_ext_data = *p + len;
kenjiArai 0:5b88d5760320 919
kenjiArai 0:5b88d5760320 920 /* Get extension ID */
kenjiArai 0:5b88d5760320 921 if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &extn_oid.len,
kenjiArai 0:5b88d5760320 922 MBEDTLS_ASN1_OID ) ) != 0 )
kenjiArai 0:5b88d5760320 923 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kenjiArai 0:5b88d5760320 924
kenjiArai 0:5b88d5760320 925 extn_oid.tag = MBEDTLS_ASN1_OID;
kenjiArai 0:5b88d5760320 926 extn_oid.p = *p;
kenjiArai 0:5b88d5760320 927 *p += extn_oid.len;
kenjiArai 0:5b88d5760320 928
kenjiArai 0:5b88d5760320 929 /* Get optional critical */
kenjiArai 0:5b88d5760320 930 if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 &&
kenjiArai 0:5b88d5760320 931 ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) )
kenjiArai 0:5b88d5760320 932 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kenjiArai 0:5b88d5760320 933
kenjiArai 0:5b88d5760320 934 /* Data should be octet string type */
kenjiArai 0:5b88d5760320 935 if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len,
kenjiArai 0:5b88d5760320 936 MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
kenjiArai 0:5b88d5760320 937 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kenjiArai 0:5b88d5760320 938
kenjiArai 0:5b88d5760320 939 end_ext_octet = *p + len;
kenjiArai 0:5b88d5760320 940
kenjiArai 0:5b88d5760320 941 if( end_ext_octet != end_ext_data )
kenjiArai 0:5b88d5760320 942 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kenjiArai 0:5b88d5760320 943 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kenjiArai 0:5b88d5760320 944
kenjiArai 0:5b88d5760320 945 /*
kenjiArai 0:5b88d5760320 946 * Detect supported extensions
kenjiArai 0:5b88d5760320 947 */
kenjiArai 0:5b88d5760320 948 ret = mbedtls_oid_get_x509_ext_type( &extn_oid, &ext_type );
kenjiArai 0:5b88d5760320 949
kenjiArai 0:5b88d5760320 950 if( ret != 0 )
kenjiArai 0:5b88d5760320 951 {
kenjiArai 0:5b88d5760320 952 /* No parser found, skip extension */
kenjiArai 0:5b88d5760320 953 *p = end_ext_octet;
kenjiArai 0:5b88d5760320 954
kenjiArai 0:5b88d5760320 955 #if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
kenjiArai 0:5b88d5760320 956 if( is_critical )
kenjiArai 0:5b88d5760320 957 {
kenjiArai 0:5b88d5760320 958 /* Data is marked as critical: fail */
kenjiArai 0:5b88d5760320 959 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kenjiArai 0:5b88d5760320 960 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
kenjiArai 0:5b88d5760320 961 }
kenjiArai 0:5b88d5760320 962 #endif
kenjiArai 0:5b88d5760320 963 continue;
kenjiArai 0:5b88d5760320 964 }
kenjiArai 0:5b88d5760320 965
kenjiArai 0:5b88d5760320 966 /* Forbid repeated extensions */
kenjiArai 0:5b88d5760320 967 if( ( crt->ext_types & ext_type ) != 0 )
kenjiArai 0:5b88d5760320 968 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS );
kenjiArai 0:5b88d5760320 969
kenjiArai 0:5b88d5760320 970 crt->ext_types |= ext_type;
kenjiArai 0:5b88d5760320 971
kenjiArai 0:5b88d5760320 972 switch( ext_type )
kenjiArai 0:5b88d5760320 973 {
kenjiArai 0:5b88d5760320 974 case MBEDTLS_X509_EXT_BASIC_CONSTRAINTS:
kenjiArai 0:5b88d5760320 975 /* Parse basic constraints */
kenjiArai 0:5b88d5760320 976 if( ( ret = x509_get_basic_constraints( p, end_ext_octet,
kenjiArai 0:5b88d5760320 977 &crt->ca_istrue, &crt->max_pathlen ) ) != 0 )
kenjiArai 0:5b88d5760320 978 return( ret );
kenjiArai 0:5b88d5760320 979 break;
kenjiArai 0:5b88d5760320 980
kenjiArai 0:5b88d5760320 981 case MBEDTLS_X509_EXT_KEY_USAGE:
kenjiArai 0:5b88d5760320 982 /* Parse key usage */
kenjiArai 0:5b88d5760320 983 if( ( ret = x509_get_key_usage( p, end_ext_octet,
kenjiArai 0:5b88d5760320 984 &crt->key_usage ) ) != 0 )
kenjiArai 0:5b88d5760320 985 return( ret );
kenjiArai 0:5b88d5760320 986 break;
kenjiArai 0:5b88d5760320 987
kenjiArai 0:5b88d5760320 988 case MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE:
kenjiArai 0:5b88d5760320 989 /* Parse extended key usage */
kenjiArai 0:5b88d5760320 990 if( ( ret = x509_get_ext_key_usage( p, end_ext_octet,
kenjiArai 0:5b88d5760320 991 &crt->ext_key_usage ) ) != 0 )
kenjiArai 0:5b88d5760320 992 return( ret );
kenjiArai 0:5b88d5760320 993 break;
kenjiArai 0:5b88d5760320 994
kenjiArai 0:5b88d5760320 995 case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME:
kenjiArai 0:5b88d5760320 996 /* Parse subject alt name */
kenjiArai 0:5b88d5760320 997 if( ( ret = x509_get_subject_alt_name( p, end_ext_octet,
kenjiArai 0:5b88d5760320 998 &crt->subject_alt_names ) ) != 0 )
kenjiArai 0:5b88d5760320 999 return( ret );
kenjiArai 0:5b88d5760320 1000 break;
kenjiArai 0:5b88d5760320 1001
kenjiArai 0:5b88d5760320 1002 case MBEDTLS_X509_EXT_NS_CERT_TYPE:
kenjiArai 0:5b88d5760320 1003 /* Parse netscape certificate type */
kenjiArai 0:5b88d5760320 1004 if( ( ret = x509_get_ns_cert_type( p, end_ext_octet,
kenjiArai 0:5b88d5760320 1005 &crt->ns_cert_type ) ) != 0 )
kenjiArai 0:5b88d5760320 1006 return( ret );
kenjiArai 0:5b88d5760320 1007 break;
kenjiArai 0:5b88d5760320 1008
kenjiArai 0:5b88d5760320 1009 case MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES:
kenjiArai 0:5b88d5760320 1010 /* Parse certificate policies type */
kenjiArai 0:5b88d5760320 1011 if( ( ret = x509_get_certificate_policies( p, end_ext_octet,
kenjiArai 0:5b88d5760320 1012 &crt->certificate_policies ) ) != 0 )
kenjiArai 0:5b88d5760320 1013 {
kenjiArai 0:5b88d5760320 1014 #if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
kenjiArai 0:5b88d5760320 1015 if( is_critical )
kenjiArai 0:5b88d5760320 1016 return( ret );
kenjiArai 0:5b88d5760320 1017 else
kenjiArai 0:5b88d5760320 1018 #endif
kenjiArai 0:5b88d5760320 1019 /*
kenjiArai 0:5b88d5760320 1020 * If MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE is returned, then we
kenjiArai 0:5b88d5760320 1021 * cannot interpret or enforce the policy. However, it is up to
kenjiArai 0:5b88d5760320 1022 * the user to choose how to enforce the policies,
kenjiArai 0:5b88d5760320 1023 * unless the extension is critical.
kenjiArai 0:5b88d5760320 1024 */
kenjiArai 0:5b88d5760320 1025 if( ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE )
kenjiArai 0:5b88d5760320 1026 return( ret );
kenjiArai 0:5b88d5760320 1027 }
kenjiArai 0:5b88d5760320 1028 break;
kenjiArai 0:5b88d5760320 1029
kenjiArai 0:5b88d5760320 1030 default:
kenjiArai 0:5b88d5760320 1031 /*
kenjiArai 0:5b88d5760320 1032 * If this is a non-critical extension, which the oid layer
kenjiArai 0:5b88d5760320 1033 * supports, but there isn't an x509 parser for it,
kenjiArai 0:5b88d5760320 1034 * skip the extension.
kenjiArai 0:5b88d5760320 1035 */
kenjiArai 0:5b88d5760320 1036 #if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
kenjiArai 0:5b88d5760320 1037 if( is_critical )
kenjiArai 0:5b88d5760320 1038 return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
kenjiArai 0:5b88d5760320 1039 else
kenjiArai 0:5b88d5760320 1040 #endif
kenjiArai 0:5b88d5760320 1041 *p = end_ext_octet;
kenjiArai 0:5b88d5760320 1042 }
kenjiArai 0:5b88d5760320 1043 }
kenjiArai 0:5b88d5760320 1044
kenjiArai 0:5b88d5760320 1045 if( *p != end )
kenjiArai 0:5b88d5760320 1046 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kenjiArai 0:5b88d5760320 1047 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kenjiArai 0:5b88d5760320 1048
kenjiArai 0:5b88d5760320 1049 return( 0 );
kenjiArai 0:5b88d5760320 1050 }
kenjiArai 0:5b88d5760320 1051
kenjiArai 0:5b88d5760320 1052 /*
kenjiArai 0:5b88d5760320 1053 * Parse and fill a single X.509 certificate in DER format
kenjiArai 0:5b88d5760320 1054 */
kenjiArai 0:5b88d5760320 1055 static int x509_crt_parse_der_core( mbedtls_x509_crt *crt,
kenjiArai 0:5b88d5760320 1056 const unsigned char *buf,
kenjiArai 0:5b88d5760320 1057 size_t buflen,
kenjiArai 0:5b88d5760320 1058 int make_copy )
kenjiArai 0:5b88d5760320 1059 {
kenjiArai 0:5b88d5760320 1060 int ret;
kenjiArai 0:5b88d5760320 1061 size_t len;
kenjiArai 0:5b88d5760320 1062 unsigned char *p, *end, *crt_end;
kenjiArai 0:5b88d5760320 1063 mbedtls_x509_buf sig_params1, sig_params2, sig_oid2;
kenjiArai 0:5b88d5760320 1064
kenjiArai 0:5b88d5760320 1065 memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) );
kenjiArai 0:5b88d5760320 1066 memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) );
kenjiArai 0:5b88d5760320 1067 memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) );
kenjiArai 0:5b88d5760320 1068
kenjiArai 0:5b88d5760320 1069 /*
kenjiArai 0:5b88d5760320 1070 * Check for valid input
kenjiArai 0:5b88d5760320 1071 */
kenjiArai 0:5b88d5760320 1072 if( crt == NULL || buf == NULL )
kenjiArai 0:5b88d5760320 1073 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
kenjiArai 0:5b88d5760320 1074
kenjiArai 0:5b88d5760320 1075 /* Use the original buffer until we figure out actual length. */
kenjiArai 0:5b88d5760320 1076 p = (unsigned char*) buf;
kenjiArai 0:5b88d5760320 1077 len = buflen;
kenjiArai 0:5b88d5760320 1078 end = p + len;
kenjiArai 0:5b88d5760320 1079
kenjiArai 0:5b88d5760320 1080 /*
kenjiArai 0:5b88d5760320 1081 * Certificate ::= SEQUENCE {
kenjiArai 0:5b88d5760320 1082 * tbsCertificate TBSCertificate,
kenjiArai 0:5b88d5760320 1083 * signatureAlgorithm AlgorithmIdentifier,
kenjiArai 0:5b88d5760320 1084 * signatureValue BIT STRING }
kenjiArai 0:5b88d5760320 1085 */
kenjiArai 0:5b88d5760320 1086 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
kenjiArai 0:5b88d5760320 1087 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
kenjiArai 0:5b88d5760320 1088 {
kenjiArai 0:5b88d5760320 1089 mbedtls_x509_crt_free( crt );
kenjiArai 0:5b88d5760320 1090 return( MBEDTLS_ERR_X509_INVALID_FORMAT );
kenjiArai 0:5b88d5760320 1091 }
kenjiArai 0:5b88d5760320 1092
kenjiArai 0:5b88d5760320 1093 end = crt_end = p + len;
kenjiArai 0:5b88d5760320 1094 crt->raw.len = crt_end - buf;
kenjiArai 0:5b88d5760320 1095 if( make_copy != 0 )
kenjiArai 0:5b88d5760320 1096 {
kenjiArai 0:5b88d5760320 1097 /* Create and populate a new buffer for the raw field. */
kenjiArai 0:5b88d5760320 1098 crt->raw.p = p = mbedtls_calloc( 1, crt->raw.len );
kenjiArai 0:5b88d5760320 1099 if( crt->raw.p == NULL )
kenjiArai 0:5b88d5760320 1100 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
kenjiArai 0:5b88d5760320 1101
kenjiArai 0:5b88d5760320 1102 memcpy( crt->raw.p, buf, crt->raw.len );
kenjiArai 0:5b88d5760320 1103 crt->own_buffer = 1;
kenjiArai 0:5b88d5760320 1104
kenjiArai 0:5b88d5760320 1105 p += crt->raw.len - len;
kenjiArai 0:5b88d5760320 1106 end = crt_end = p + len;
kenjiArai 0:5b88d5760320 1107 }
kenjiArai 0:5b88d5760320 1108 else
kenjiArai 0:5b88d5760320 1109 {
kenjiArai 0:5b88d5760320 1110 crt->raw.p = (unsigned char*) buf;
kenjiArai 0:5b88d5760320 1111 crt->own_buffer = 0;
kenjiArai 0:5b88d5760320 1112 }
kenjiArai 0:5b88d5760320 1113
kenjiArai 0:5b88d5760320 1114 /*
kenjiArai 0:5b88d5760320 1115 * TBSCertificate ::= SEQUENCE {
kenjiArai 0:5b88d5760320 1116 */
kenjiArai 0:5b88d5760320 1117 crt->tbs.p = p;
kenjiArai 0:5b88d5760320 1118
kenjiArai 0:5b88d5760320 1119 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
kenjiArai 0:5b88d5760320 1120 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
kenjiArai 0:5b88d5760320 1121 {
kenjiArai 0:5b88d5760320 1122 mbedtls_x509_crt_free( crt );
kenjiArai 0:5b88d5760320 1123 return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
kenjiArai 0:5b88d5760320 1124 }
kenjiArai 0:5b88d5760320 1125
kenjiArai 0:5b88d5760320 1126 end = p + len;
kenjiArai 0:5b88d5760320 1127 crt->tbs.len = end - crt->tbs.p;
kenjiArai 0:5b88d5760320 1128
kenjiArai 0:5b88d5760320 1129 /*
kenjiArai 0:5b88d5760320 1130 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
kenjiArai 0:5b88d5760320 1131 *
kenjiArai 0:5b88d5760320 1132 * CertificateSerialNumber ::= INTEGER
kenjiArai 0:5b88d5760320 1133 *
kenjiArai 0:5b88d5760320 1134 * signature AlgorithmIdentifier
kenjiArai 0:5b88d5760320 1135 */
kenjiArai 0:5b88d5760320 1136 if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 ||
kenjiArai 0:5b88d5760320 1137 ( ret = mbedtls_x509_get_serial( &p, end, &crt->serial ) ) != 0 ||
kenjiArai 0:5b88d5760320 1138 ( ret = mbedtls_x509_get_alg( &p, end, &crt->sig_oid,
kenjiArai 0:5b88d5760320 1139 &sig_params1 ) ) != 0 )
kenjiArai 0:5b88d5760320 1140 {
kenjiArai 0:5b88d5760320 1141 mbedtls_x509_crt_free( crt );
kenjiArai 0:5b88d5760320 1142 return( ret );
kenjiArai 0:5b88d5760320 1143 }
kenjiArai 0:5b88d5760320 1144
kenjiArai 0:5b88d5760320 1145 if( crt->version < 0 || crt->version > 2 )
kenjiArai 0:5b88d5760320 1146 {
kenjiArai 0:5b88d5760320 1147 mbedtls_x509_crt_free( crt );
kenjiArai 0:5b88d5760320 1148 return( MBEDTLS_ERR_X509_UNKNOWN_VERSION );
kenjiArai 0:5b88d5760320 1149 }
kenjiArai 0:5b88d5760320 1150
kenjiArai 0:5b88d5760320 1151 crt->version++;
kenjiArai 0:5b88d5760320 1152
kenjiArai 0:5b88d5760320 1153 if( ( ret = mbedtls_x509_get_sig_alg( &crt->sig_oid, &sig_params1,
kenjiArai 0:5b88d5760320 1154 &crt->sig_md, &crt->sig_pk,
kenjiArai 0:5b88d5760320 1155 &crt->sig_opts ) ) != 0 )
kenjiArai 0:5b88d5760320 1156 {
kenjiArai 0:5b88d5760320 1157 mbedtls_x509_crt_free( crt );
kenjiArai 0:5b88d5760320 1158 return( ret );
kenjiArai 0:5b88d5760320 1159 }
kenjiArai 0:5b88d5760320 1160
kenjiArai 0:5b88d5760320 1161 /*
kenjiArai 0:5b88d5760320 1162 * issuer Name
kenjiArai 0:5b88d5760320 1163 */
kenjiArai 0:5b88d5760320 1164 crt->issuer_raw.p = p;
kenjiArai 0:5b88d5760320 1165
kenjiArai 0:5b88d5760320 1166 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
kenjiArai 0:5b88d5760320 1167 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
kenjiArai 0:5b88d5760320 1168 {
kenjiArai 0:5b88d5760320 1169 mbedtls_x509_crt_free( crt );
kenjiArai 0:5b88d5760320 1170 return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
kenjiArai 0:5b88d5760320 1171 }
kenjiArai 0:5b88d5760320 1172
kenjiArai 0:5b88d5760320 1173 if( ( ret = mbedtls_x509_get_name( &p, p + len, &crt->issuer ) ) != 0 )
kenjiArai 0:5b88d5760320 1174 {
kenjiArai 0:5b88d5760320 1175 mbedtls_x509_crt_free( crt );
kenjiArai 0:5b88d5760320 1176 return( ret );
kenjiArai 0:5b88d5760320 1177 }
kenjiArai 0:5b88d5760320 1178
kenjiArai 0:5b88d5760320 1179 crt->issuer_raw.len = p - crt->issuer_raw.p;
kenjiArai 0:5b88d5760320 1180
kenjiArai 0:5b88d5760320 1181 /*
kenjiArai 0:5b88d5760320 1182 * Validity ::= SEQUENCE {
kenjiArai 0:5b88d5760320 1183 * notBefore Time,
kenjiArai 0:5b88d5760320 1184 * notAfter Time }
kenjiArai 0:5b88d5760320 1185 *
kenjiArai 0:5b88d5760320 1186 */
kenjiArai 0:5b88d5760320 1187 if( ( ret = x509_get_dates( &p, end, &crt->valid_from,
kenjiArai 0:5b88d5760320 1188 &crt->valid_to ) ) != 0 )
kenjiArai 0:5b88d5760320 1189 {
kenjiArai 0:5b88d5760320 1190 mbedtls_x509_crt_free( crt );
kenjiArai 0:5b88d5760320 1191 return( ret );
kenjiArai 0:5b88d5760320 1192 }
kenjiArai 0:5b88d5760320 1193
kenjiArai 0:5b88d5760320 1194 /*
kenjiArai 0:5b88d5760320 1195 * subject Name
kenjiArai 0:5b88d5760320 1196 */
kenjiArai 0:5b88d5760320 1197 crt->subject_raw.p = p;
kenjiArai 0:5b88d5760320 1198
kenjiArai 0:5b88d5760320 1199 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
kenjiArai 0:5b88d5760320 1200 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
kenjiArai 0:5b88d5760320 1201 {
kenjiArai 0:5b88d5760320 1202 mbedtls_x509_crt_free( crt );
kenjiArai 0:5b88d5760320 1203 return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
kenjiArai 0:5b88d5760320 1204 }
kenjiArai 0:5b88d5760320 1205
kenjiArai 0:5b88d5760320 1206 if( len && ( ret = mbedtls_x509_get_name( &p, p + len, &crt->subject ) ) != 0 )
kenjiArai 0:5b88d5760320 1207 {
kenjiArai 0:5b88d5760320 1208 mbedtls_x509_crt_free( crt );
kenjiArai 0:5b88d5760320 1209 return( ret );
kenjiArai 0:5b88d5760320 1210 }
kenjiArai 0:5b88d5760320 1211
kenjiArai 0:5b88d5760320 1212 crt->subject_raw.len = p - crt->subject_raw.p;
kenjiArai 0:5b88d5760320 1213
kenjiArai 0:5b88d5760320 1214 /*
kenjiArai 0:5b88d5760320 1215 * SubjectPublicKeyInfo
kenjiArai 0:5b88d5760320 1216 */
kenjiArai 0:5b88d5760320 1217 crt->pk_raw.p = p;
kenjiArai 0:5b88d5760320 1218 if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &crt->pk ) ) != 0 )
kenjiArai 0:5b88d5760320 1219 {
kenjiArai 0:5b88d5760320 1220 mbedtls_x509_crt_free( crt );
kenjiArai 0:5b88d5760320 1221 return( ret );
kenjiArai 0:5b88d5760320 1222 }
kenjiArai 0:5b88d5760320 1223 crt->pk_raw.len = p - crt->pk_raw.p;
kenjiArai 0:5b88d5760320 1224
kenjiArai 0:5b88d5760320 1225 /*
kenjiArai 0:5b88d5760320 1226 * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
kenjiArai 0:5b88d5760320 1227 * -- If present, version shall be v2 or v3
kenjiArai 0:5b88d5760320 1228 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
kenjiArai 0:5b88d5760320 1229 * -- If present, version shall be v2 or v3
kenjiArai 0:5b88d5760320 1230 * extensions [3] EXPLICIT Extensions OPTIONAL
kenjiArai 0:5b88d5760320 1231 * -- If present, version shall be v3
kenjiArai 0:5b88d5760320 1232 */
kenjiArai 0:5b88d5760320 1233 if( crt->version == 2 || crt->version == 3 )
kenjiArai 0:5b88d5760320 1234 {
kenjiArai 0:5b88d5760320 1235 ret = x509_get_uid( &p, end, &crt->issuer_id, 1 );
kenjiArai 0:5b88d5760320 1236 if( ret != 0 )
kenjiArai 0:5b88d5760320 1237 {
kenjiArai 0:5b88d5760320 1238 mbedtls_x509_crt_free( crt );
kenjiArai 0:5b88d5760320 1239 return( ret );
kenjiArai 0:5b88d5760320 1240 }
kenjiArai 0:5b88d5760320 1241 }
kenjiArai 0:5b88d5760320 1242
kenjiArai 0:5b88d5760320 1243 if( crt->version == 2 || crt->version == 3 )
kenjiArai 0:5b88d5760320 1244 {
kenjiArai 0:5b88d5760320 1245 ret = x509_get_uid( &p, end, &crt->subject_id, 2 );
kenjiArai 0:5b88d5760320 1246 if( ret != 0 )
kenjiArai 0:5b88d5760320 1247 {
kenjiArai 0:5b88d5760320 1248 mbedtls_x509_crt_free( crt );
kenjiArai 0:5b88d5760320 1249 return( ret );
kenjiArai 0:5b88d5760320 1250 }
kenjiArai 0:5b88d5760320 1251 }
kenjiArai 0:5b88d5760320 1252
kenjiArai 0:5b88d5760320 1253 #if !defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3)
kenjiArai 0:5b88d5760320 1254 if( crt->version == 3 )
kenjiArai 0:5b88d5760320 1255 #endif
kenjiArai 0:5b88d5760320 1256 {
kenjiArai 0:5b88d5760320 1257 ret = x509_get_crt_ext( &p, end, crt );
kenjiArai 0:5b88d5760320 1258 if( ret != 0 )
kenjiArai 0:5b88d5760320 1259 {
kenjiArai 0:5b88d5760320 1260 mbedtls_x509_crt_free( crt );
kenjiArai 0:5b88d5760320 1261 return( ret );
kenjiArai 0:5b88d5760320 1262 }
kenjiArai 0:5b88d5760320 1263 }
kenjiArai 0:5b88d5760320 1264
kenjiArai 0:5b88d5760320 1265 if( p != end )
kenjiArai 0:5b88d5760320 1266 {
kenjiArai 0:5b88d5760320 1267 mbedtls_x509_crt_free( crt );
kenjiArai 0:5b88d5760320 1268 return( MBEDTLS_ERR_X509_INVALID_FORMAT +
kenjiArai 0:5b88d5760320 1269 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kenjiArai 0:5b88d5760320 1270 }
kenjiArai 0:5b88d5760320 1271
kenjiArai 0:5b88d5760320 1272 end = crt_end;
kenjiArai 0:5b88d5760320 1273
kenjiArai 0:5b88d5760320 1274 /*
kenjiArai 0:5b88d5760320 1275 * }
kenjiArai 0:5b88d5760320 1276 * -- end of TBSCertificate
kenjiArai 0:5b88d5760320 1277 *
kenjiArai 0:5b88d5760320 1278 * signatureAlgorithm AlgorithmIdentifier,
kenjiArai 0:5b88d5760320 1279 * signatureValue BIT STRING
kenjiArai 0:5b88d5760320 1280 */
kenjiArai 0:5b88d5760320 1281 if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 )
kenjiArai 0:5b88d5760320 1282 {
kenjiArai 0:5b88d5760320 1283 mbedtls_x509_crt_free( crt );
kenjiArai 0:5b88d5760320 1284 return( ret );
kenjiArai 0:5b88d5760320 1285 }
kenjiArai 0:5b88d5760320 1286
kenjiArai 0:5b88d5760320 1287 if( crt->sig_oid.len != sig_oid2.len ||
kenjiArai 0:5b88d5760320 1288 memcmp( crt->sig_oid.p, sig_oid2.p, crt->sig_oid.len ) != 0 ||
kenjiArai 0:5b88d5760320 1289 sig_params1.len != sig_params2.len ||
kenjiArai 0:5b88d5760320 1290 ( sig_params1.len != 0 &&
kenjiArai 0:5b88d5760320 1291 memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) )
kenjiArai 0:5b88d5760320 1292 {
kenjiArai 0:5b88d5760320 1293 mbedtls_x509_crt_free( crt );
kenjiArai 0:5b88d5760320 1294 return( MBEDTLS_ERR_X509_SIG_MISMATCH );
kenjiArai 0:5b88d5760320 1295 }
kenjiArai 0:5b88d5760320 1296
kenjiArai 0:5b88d5760320 1297 if( ( ret = mbedtls_x509_get_sig( &p, end, &crt->sig ) ) != 0 )
kenjiArai 0:5b88d5760320 1298 {
kenjiArai 0:5b88d5760320 1299 mbedtls_x509_crt_free( crt );
kenjiArai 0:5b88d5760320 1300 return( ret );
kenjiArai 0:5b88d5760320 1301 }
kenjiArai 0:5b88d5760320 1302
kenjiArai 0:5b88d5760320 1303 if( p != end )
kenjiArai 0:5b88d5760320 1304 {
kenjiArai 0:5b88d5760320 1305 mbedtls_x509_crt_free( crt );
kenjiArai 0:5b88d5760320 1306 return( MBEDTLS_ERR_X509_INVALID_FORMAT +
kenjiArai 0:5b88d5760320 1307 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kenjiArai 0:5b88d5760320 1308 }
kenjiArai 0:5b88d5760320 1309
kenjiArai 0:5b88d5760320 1310 return( 0 );
kenjiArai 0:5b88d5760320 1311 }
kenjiArai 0:5b88d5760320 1312
kenjiArai 0:5b88d5760320 1313 /*
kenjiArai 0:5b88d5760320 1314 * Parse one X.509 certificate in DER format from a buffer and add them to a
kenjiArai 0:5b88d5760320 1315 * chained list
kenjiArai 0:5b88d5760320 1316 */
kenjiArai 0:5b88d5760320 1317 static int mbedtls_x509_crt_parse_der_internal( mbedtls_x509_crt *chain,
kenjiArai 0:5b88d5760320 1318 const unsigned char *buf,
kenjiArai 0:5b88d5760320 1319 size_t buflen,
kenjiArai 0:5b88d5760320 1320 int make_copy )
kenjiArai 0:5b88d5760320 1321 {
kenjiArai 0:5b88d5760320 1322 int ret;
kenjiArai 0:5b88d5760320 1323 mbedtls_x509_crt *crt = chain, *prev = NULL;
kenjiArai 0:5b88d5760320 1324
kenjiArai 0:5b88d5760320 1325 /*
kenjiArai 0:5b88d5760320 1326 * Check for valid input
kenjiArai 0:5b88d5760320 1327 */
kenjiArai 0:5b88d5760320 1328 if( crt == NULL || buf == NULL )
kenjiArai 0:5b88d5760320 1329 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
kenjiArai 0:5b88d5760320 1330
kenjiArai 0:5b88d5760320 1331 while( crt->version != 0 && crt->next != NULL )
kenjiArai 0:5b88d5760320 1332 {
kenjiArai 0:5b88d5760320 1333 prev = crt;
kenjiArai 0:5b88d5760320 1334 crt = crt->next;
kenjiArai 0:5b88d5760320 1335 }
kenjiArai 0:5b88d5760320 1336
kenjiArai 0:5b88d5760320 1337 /*
kenjiArai 0:5b88d5760320 1338 * Add new certificate on the end of the chain if needed.
kenjiArai 0:5b88d5760320 1339 */
kenjiArai 0:5b88d5760320 1340 if( crt->version != 0 && crt->next == NULL )
kenjiArai 0:5b88d5760320 1341 {
kenjiArai 0:5b88d5760320 1342 crt->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) );
kenjiArai 0:5b88d5760320 1343
kenjiArai 0:5b88d5760320 1344 if( crt->next == NULL )
kenjiArai 0:5b88d5760320 1345 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
kenjiArai 0:5b88d5760320 1346
kenjiArai 0:5b88d5760320 1347 prev = crt;
kenjiArai 0:5b88d5760320 1348 mbedtls_x509_crt_init( crt->next );
kenjiArai 0:5b88d5760320 1349 crt = crt->next;
kenjiArai 0:5b88d5760320 1350 }
kenjiArai 0:5b88d5760320 1351
kenjiArai 0:5b88d5760320 1352 if( ( ret = x509_crt_parse_der_core( crt, buf, buflen, make_copy ) ) != 0 )
kenjiArai 0:5b88d5760320 1353 {
kenjiArai 0:5b88d5760320 1354 if( prev )
kenjiArai 0:5b88d5760320 1355 prev->next = NULL;
kenjiArai 0:5b88d5760320 1356
kenjiArai 0:5b88d5760320 1357 if( crt != chain )
kenjiArai 0:5b88d5760320 1358 mbedtls_free( crt );
kenjiArai 0:5b88d5760320 1359
kenjiArai 0:5b88d5760320 1360 return( ret );
kenjiArai 0:5b88d5760320 1361 }
kenjiArai 0:5b88d5760320 1362
kenjiArai 0:5b88d5760320 1363 return( 0 );
kenjiArai 0:5b88d5760320 1364 }
kenjiArai 0:5b88d5760320 1365
kenjiArai 0:5b88d5760320 1366 int mbedtls_x509_crt_parse_der_nocopy( mbedtls_x509_crt *chain,
kenjiArai 0:5b88d5760320 1367 const unsigned char *buf,
kenjiArai 0:5b88d5760320 1368 size_t buflen )
kenjiArai 0:5b88d5760320 1369 {
kenjiArai 0:5b88d5760320 1370 return( mbedtls_x509_crt_parse_der_internal( chain, buf, buflen, 0 ) );
kenjiArai 0:5b88d5760320 1371 }
kenjiArai 0:5b88d5760320 1372
kenjiArai 0:5b88d5760320 1373 int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain,
kenjiArai 0:5b88d5760320 1374 const unsigned char *buf,
kenjiArai 0:5b88d5760320 1375 size_t buflen )
kenjiArai 0:5b88d5760320 1376 {
kenjiArai 0:5b88d5760320 1377 return( mbedtls_x509_crt_parse_der_internal( chain, buf, buflen, 1 ) );
kenjiArai 0:5b88d5760320 1378 }
kenjiArai 0:5b88d5760320 1379
kenjiArai 0:5b88d5760320 1380 /*
kenjiArai 0:5b88d5760320 1381 * Parse one or more PEM certificates from a buffer and add them to the chained
kenjiArai 0:5b88d5760320 1382 * list
kenjiArai 0:5b88d5760320 1383 */
kenjiArai 0:5b88d5760320 1384 int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain,
kenjiArai 0:5b88d5760320 1385 const unsigned char *buf,
kenjiArai 0:5b88d5760320 1386 size_t buflen )
kenjiArai 0:5b88d5760320 1387 {
kenjiArai 0:5b88d5760320 1388 #if defined(MBEDTLS_PEM_PARSE_C)
kenjiArai 0:5b88d5760320 1389 int success = 0, first_error = 0, total_failed = 0;
kenjiArai 0:5b88d5760320 1390 int buf_format = MBEDTLS_X509_FORMAT_DER;
kenjiArai 0:5b88d5760320 1391 #endif
kenjiArai 0:5b88d5760320 1392
kenjiArai 0:5b88d5760320 1393 /*
kenjiArai 0:5b88d5760320 1394 * Check for valid input
kenjiArai 0:5b88d5760320 1395 */
kenjiArai 0:5b88d5760320 1396 if( chain == NULL || buf == NULL )
kenjiArai 0:5b88d5760320 1397 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
kenjiArai 0:5b88d5760320 1398
kenjiArai 0:5b88d5760320 1399 /*
kenjiArai 0:5b88d5760320 1400 * Determine buffer content. Buffer contains either one DER certificate or
kenjiArai 0:5b88d5760320 1401 * one or more PEM certificates.
kenjiArai 0:5b88d5760320 1402 */
kenjiArai 0:5b88d5760320 1403 #if defined(MBEDTLS_PEM_PARSE_C)
kenjiArai 0:5b88d5760320 1404 if( buflen != 0 && buf[buflen - 1] == '\0' &&
kenjiArai 0:5b88d5760320 1405 strstr( (const char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL )
kenjiArai 0:5b88d5760320 1406 {
kenjiArai 0:5b88d5760320 1407 buf_format = MBEDTLS_X509_FORMAT_PEM;
kenjiArai 0:5b88d5760320 1408 }
kenjiArai 0:5b88d5760320 1409
kenjiArai 0:5b88d5760320 1410 if( buf_format == MBEDTLS_X509_FORMAT_DER )
kenjiArai 0:5b88d5760320 1411 return mbedtls_x509_crt_parse_der( chain, buf, buflen );
kenjiArai 0:5b88d5760320 1412 #else
kenjiArai 0:5b88d5760320 1413 return mbedtls_x509_crt_parse_der( chain, buf, buflen );
kenjiArai 0:5b88d5760320 1414 #endif
kenjiArai 0:5b88d5760320 1415
kenjiArai 0:5b88d5760320 1416 #if defined(MBEDTLS_PEM_PARSE_C)
kenjiArai 0:5b88d5760320 1417 if( buf_format == MBEDTLS_X509_FORMAT_PEM )
kenjiArai 0:5b88d5760320 1418 {
kenjiArai 0:5b88d5760320 1419 int ret;
kenjiArai 0:5b88d5760320 1420 mbedtls_pem_context pem;
kenjiArai 0:5b88d5760320 1421
kenjiArai 0:5b88d5760320 1422 /* 1 rather than 0 since the terminating NULL byte is counted in */
kenjiArai 0:5b88d5760320 1423 while( buflen > 1 )
kenjiArai 0:5b88d5760320 1424 {
kenjiArai 0:5b88d5760320 1425 size_t use_len;
kenjiArai 0:5b88d5760320 1426 mbedtls_pem_init( &pem );
kenjiArai 0:5b88d5760320 1427
kenjiArai 0:5b88d5760320 1428 /* If we get there, we know the string is null-terminated */
kenjiArai 0:5b88d5760320 1429 ret = mbedtls_pem_read_buffer( &pem,
kenjiArai 0:5b88d5760320 1430 "-----BEGIN CERTIFICATE-----",
kenjiArai 0:5b88d5760320 1431 "-----END CERTIFICATE-----",
kenjiArai 0:5b88d5760320 1432 buf, NULL, 0, &use_len );
kenjiArai 0:5b88d5760320 1433
kenjiArai 0:5b88d5760320 1434 if( ret == 0 )
kenjiArai 0:5b88d5760320 1435 {
kenjiArai 0:5b88d5760320 1436 /*
kenjiArai 0:5b88d5760320 1437 * Was PEM encoded
kenjiArai 0:5b88d5760320 1438 */
kenjiArai 0:5b88d5760320 1439 buflen -= use_len;
kenjiArai 0:5b88d5760320 1440 buf += use_len;
kenjiArai 0:5b88d5760320 1441 }
kenjiArai 0:5b88d5760320 1442 else if( ret == MBEDTLS_ERR_PEM_BAD_INPUT_DATA )
kenjiArai 0:5b88d5760320 1443 {
kenjiArai 0:5b88d5760320 1444 return( ret );
kenjiArai 0:5b88d5760320 1445 }
kenjiArai 0:5b88d5760320 1446 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
kenjiArai 0:5b88d5760320 1447 {
kenjiArai 0:5b88d5760320 1448 mbedtls_pem_free( &pem );
kenjiArai 0:5b88d5760320 1449
kenjiArai 0:5b88d5760320 1450 /*
kenjiArai 0:5b88d5760320 1451 * PEM header and footer were found
kenjiArai 0:5b88d5760320 1452 */
kenjiArai 0:5b88d5760320 1453 buflen -= use_len;
kenjiArai 0:5b88d5760320 1454 buf += use_len;
kenjiArai 0:5b88d5760320 1455
kenjiArai 0:5b88d5760320 1456 if( first_error == 0 )
kenjiArai 0:5b88d5760320 1457 first_error = ret;
kenjiArai 0:5b88d5760320 1458
kenjiArai 0:5b88d5760320 1459 total_failed++;
kenjiArai 0:5b88d5760320 1460 continue;
kenjiArai 0:5b88d5760320 1461 }
kenjiArai 0:5b88d5760320 1462 else
kenjiArai 0:5b88d5760320 1463 break;
kenjiArai 0:5b88d5760320 1464
kenjiArai 0:5b88d5760320 1465 ret = mbedtls_x509_crt_parse_der( chain, pem.buf, pem.buflen );
kenjiArai 0:5b88d5760320 1466
kenjiArai 0:5b88d5760320 1467 mbedtls_pem_free( &pem );
kenjiArai 0:5b88d5760320 1468
kenjiArai 0:5b88d5760320 1469 if( ret != 0 )
kenjiArai 0:5b88d5760320 1470 {
kenjiArai 0:5b88d5760320 1471 /*
kenjiArai 0:5b88d5760320 1472 * Quit parsing on a memory error
kenjiArai 0:5b88d5760320 1473 */
kenjiArai 0:5b88d5760320 1474 if( ret == MBEDTLS_ERR_X509_ALLOC_FAILED )
kenjiArai 0:5b88d5760320 1475 return( ret );
kenjiArai 0:5b88d5760320 1476
kenjiArai 0:5b88d5760320 1477 if( first_error == 0 )
kenjiArai 0:5b88d5760320 1478 first_error = ret;
kenjiArai 0:5b88d5760320 1479
kenjiArai 0:5b88d5760320 1480 total_failed++;
kenjiArai 0:5b88d5760320 1481 continue;
kenjiArai 0:5b88d5760320 1482 }
kenjiArai 0:5b88d5760320 1483
kenjiArai 0:5b88d5760320 1484 success = 1;
kenjiArai 0:5b88d5760320 1485 }
kenjiArai 0:5b88d5760320 1486 }
kenjiArai 0:5b88d5760320 1487
kenjiArai 0:5b88d5760320 1488 if( success )
kenjiArai 0:5b88d5760320 1489 return( total_failed );
kenjiArai 0:5b88d5760320 1490 else if( first_error )
kenjiArai 0:5b88d5760320 1491 return( first_error );
kenjiArai 0:5b88d5760320 1492 else
kenjiArai 0:5b88d5760320 1493 return( MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT );
kenjiArai 0:5b88d5760320 1494 #endif /* MBEDTLS_PEM_PARSE_C */
kenjiArai 0:5b88d5760320 1495 }
kenjiArai 0:5b88d5760320 1496
kenjiArai 0:5b88d5760320 1497 #if defined(MBEDTLS_FS_IO)
kenjiArai 0:5b88d5760320 1498 /*
kenjiArai 0:5b88d5760320 1499 * Load one or more certificates and add them to the chained list
kenjiArai 0:5b88d5760320 1500 */
kenjiArai 0:5b88d5760320 1501 int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path )
kenjiArai 0:5b88d5760320 1502 {
kenjiArai 0:5b88d5760320 1503 int ret;
kenjiArai 0:5b88d5760320 1504 size_t n;
kenjiArai 0:5b88d5760320 1505 unsigned char *buf;
kenjiArai 0:5b88d5760320 1506
kenjiArai 0:5b88d5760320 1507 if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 )
kenjiArai 0:5b88d5760320 1508 return( ret );
kenjiArai 0:5b88d5760320 1509
kenjiArai 0:5b88d5760320 1510 ret = mbedtls_x509_crt_parse( chain, buf, n );
kenjiArai 0:5b88d5760320 1511
kenjiArai 0:5b88d5760320 1512 mbedtls_platform_zeroize( buf, n );
kenjiArai 0:5b88d5760320 1513 mbedtls_free( buf );
kenjiArai 0:5b88d5760320 1514
kenjiArai 0:5b88d5760320 1515 return( ret );
kenjiArai 0:5b88d5760320 1516 }
kenjiArai 0:5b88d5760320 1517
kenjiArai 0:5b88d5760320 1518 int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
kenjiArai 0:5b88d5760320 1519 {
kenjiArai 0:5b88d5760320 1520 int ret = 0;
kenjiArai 0:5b88d5760320 1521 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
kenjiArai 0:5b88d5760320 1522 int w_ret;
kenjiArai 0:5b88d5760320 1523 WCHAR szDir[MAX_PATH];
kenjiArai 0:5b88d5760320 1524 char filename[MAX_PATH];
kenjiArai 0:5b88d5760320 1525 char *p;
kenjiArai 0:5b88d5760320 1526 size_t len = strlen( path );
kenjiArai 0:5b88d5760320 1527
kenjiArai 0:5b88d5760320 1528 WIN32_FIND_DATAW file_data;
kenjiArai 0:5b88d5760320 1529 HANDLE hFind;
kenjiArai 0:5b88d5760320 1530
kenjiArai 0:5b88d5760320 1531 if( len > MAX_PATH - 3 )
kenjiArai 0:5b88d5760320 1532 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
kenjiArai 0:5b88d5760320 1533
kenjiArai 0:5b88d5760320 1534 memset( szDir, 0, sizeof(szDir) );
kenjiArai 0:5b88d5760320 1535 memset( filename, 0, MAX_PATH );
kenjiArai 0:5b88d5760320 1536 memcpy( filename, path, len );
kenjiArai 0:5b88d5760320 1537 filename[len++] = '\\';
kenjiArai 0:5b88d5760320 1538 p = filename + len;
kenjiArai 0:5b88d5760320 1539 filename[len++] = '*';
kenjiArai 0:5b88d5760320 1540
kenjiArai 0:5b88d5760320 1541 w_ret = MultiByteToWideChar( CP_ACP, 0, filename, (int)len, szDir,
kenjiArai 0:5b88d5760320 1542 MAX_PATH - 3 );
kenjiArai 0:5b88d5760320 1543 if( w_ret == 0 )
kenjiArai 0:5b88d5760320 1544 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
kenjiArai 0:5b88d5760320 1545
kenjiArai 0:5b88d5760320 1546 hFind = FindFirstFileW( szDir, &file_data );
kenjiArai 0:5b88d5760320 1547 if( hFind == INVALID_HANDLE_VALUE )
kenjiArai 0:5b88d5760320 1548 return( MBEDTLS_ERR_X509_FILE_IO_ERROR );
kenjiArai 0:5b88d5760320 1549
kenjiArai 0:5b88d5760320 1550 len = MAX_PATH - len;
kenjiArai 0:5b88d5760320 1551 do
kenjiArai 0:5b88d5760320 1552 {
kenjiArai 0:5b88d5760320 1553 memset( p, 0, len );
kenjiArai 0:5b88d5760320 1554
kenjiArai 0:5b88d5760320 1555 if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
kenjiArai 0:5b88d5760320 1556 continue;
kenjiArai 0:5b88d5760320 1557
kenjiArai 0:5b88d5760320 1558 w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName,
kenjiArai 0:5b88d5760320 1559 lstrlenW( file_data.cFileName ),
kenjiArai 0:5b88d5760320 1560 p, (int) len - 1,
kenjiArai 0:5b88d5760320 1561 NULL, NULL );
kenjiArai 0:5b88d5760320 1562 if( w_ret == 0 )
kenjiArai 0:5b88d5760320 1563 {
kenjiArai 0:5b88d5760320 1564 ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
kenjiArai 0:5b88d5760320 1565 goto cleanup;
kenjiArai 0:5b88d5760320 1566 }
kenjiArai 0:5b88d5760320 1567
kenjiArai 0:5b88d5760320 1568 w_ret = mbedtls_x509_crt_parse_file( chain, filename );
kenjiArai 0:5b88d5760320 1569 if( w_ret < 0 )
kenjiArai 0:5b88d5760320 1570 ret++;
kenjiArai 0:5b88d5760320 1571 else
kenjiArai 0:5b88d5760320 1572 ret += w_ret;
kenjiArai 0:5b88d5760320 1573 }
kenjiArai 0:5b88d5760320 1574 while( FindNextFileW( hFind, &file_data ) != 0 );
kenjiArai 0:5b88d5760320 1575
kenjiArai 0:5b88d5760320 1576 if( GetLastError() != ERROR_NO_MORE_FILES )
kenjiArai 0:5b88d5760320 1577 ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
kenjiArai 0:5b88d5760320 1578
kenjiArai 0:5b88d5760320 1579 cleanup:
kenjiArai 0:5b88d5760320 1580 FindClose( hFind );
kenjiArai 0:5b88d5760320 1581 #else /* _WIN32 */
kenjiArai 0:5b88d5760320 1582 int t_ret;
kenjiArai 0:5b88d5760320 1583 int snp_ret;
kenjiArai 0:5b88d5760320 1584 struct stat sb;
kenjiArai 0:5b88d5760320 1585 struct dirent *entry;
kenjiArai 0:5b88d5760320 1586 char entry_name[MBEDTLS_X509_MAX_FILE_PATH_LEN];
kenjiArai 0:5b88d5760320 1587 DIR *dir = opendir( path );
kenjiArai 0:5b88d5760320 1588
kenjiArai 0:5b88d5760320 1589 if( dir == NULL )
kenjiArai 0:5b88d5760320 1590 return( MBEDTLS_ERR_X509_FILE_IO_ERROR );
kenjiArai 0:5b88d5760320 1591
kenjiArai 0:5b88d5760320 1592 #if defined(MBEDTLS_THREADING_C)
kenjiArai 0:5b88d5760320 1593 if( ( ret = mbedtls_mutex_lock( &mbedtls_threading_readdir_mutex ) ) != 0 )
kenjiArai 0:5b88d5760320 1594 {
kenjiArai 0:5b88d5760320 1595 closedir( dir );
kenjiArai 0:5b88d5760320 1596 return( ret );
kenjiArai 0:5b88d5760320 1597 }
kenjiArai 0:5b88d5760320 1598 #endif /* MBEDTLS_THREADING_C */
kenjiArai 0:5b88d5760320 1599
kenjiArai 0:5b88d5760320 1600 while( ( entry = readdir( dir ) ) != NULL )
kenjiArai 0:5b88d5760320 1601 {
kenjiArai 0:5b88d5760320 1602 snp_ret = mbedtls_snprintf( entry_name, sizeof entry_name,
kenjiArai 0:5b88d5760320 1603 "%s/%s", path, entry->d_name );
kenjiArai 0:5b88d5760320 1604
kenjiArai 0:5b88d5760320 1605 if( snp_ret < 0 || (size_t)snp_ret >= sizeof entry_name )
kenjiArai 0:5b88d5760320 1606 {
kenjiArai 0:5b88d5760320 1607 ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
kenjiArai 0:5b88d5760320 1608 goto cleanup;
kenjiArai 0:5b88d5760320 1609 }
kenjiArai 0:5b88d5760320 1610 else if( stat( entry_name, &sb ) == -1 )
kenjiArai 0:5b88d5760320 1611 {
kenjiArai 0:5b88d5760320 1612 ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
kenjiArai 0:5b88d5760320 1613 goto cleanup;
kenjiArai 0:5b88d5760320 1614 }
kenjiArai 0:5b88d5760320 1615
kenjiArai 0:5b88d5760320 1616 if( !S_ISREG( sb.st_mode ) )
kenjiArai 0:5b88d5760320 1617 continue;
kenjiArai 0:5b88d5760320 1618
kenjiArai 0:5b88d5760320 1619 // Ignore parse errors
kenjiArai 0:5b88d5760320 1620 //
kenjiArai 0:5b88d5760320 1621 t_ret = mbedtls_x509_crt_parse_file( chain, entry_name );
kenjiArai 0:5b88d5760320 1622 if( t_ret < 0 )
kenjiArai 0:5b88d5760320 1623 ret++;
kenjiArai 0:5b88d5760320 1624 else
kenjiArai 0:5b88d5760320 1625 ret += t_ret;
kenjiArai 0:5b88d5760320 1626 }
kenjiArai 0:5b88d5760320 1627
kenjiArai 0:5b88d5760320 1628 cleanup:
kenjiArai 0:5b88d5760320 1629 closedir( dir );
kenjiArai 0:5b88d5760320 1630
kenjiArai 0:5b88d5760320 1631 #if defined(MBEDTLS_THREADING_C)
kenjiArai 0:5b88d5760320 1632 if( mbedtls_mutex_unlock( &mbedtls_threading_readdir_mutex ) != 0 )
kenjiArai 0:5b88d5760320 1633 ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR;
kenjiArai 0:5b88d5760320 1634 #endif /* MBEDTLS_THREADING_C */
kenjiArai 0:5b88d5760320 1635
kenjiArai 0:5b88d5760320 1636 #endif /* _WIN32 */
kenjiArai 0:5b88d5760320 1637
kenjiArai 0:5b88d5760320 1638 return( ret );
kenjiArai 0:5b88d5760320 1639 }
kenjiArai 0:5b88d5760320 1640 #endif /* MBEDTLS_FS_IO */
kenjiArai 0:5b88d5760320 1641
kenjiArai 0:5b88d5760320 1642 /*
kenjiArai 0:5b88d5760320 1643 * OtherName ::= SEQUENCE {
kenjiArai 0:5b88d5760320 1644 * type-id OBJECT IDENTIFIER,
kenjiArai 0:5b88d5760320 1645 * value [0] EXPLICIT ANY DEFINED BY type-id }
kenjiArai 0:5b88d5760320 1646 *
kenjiArai 0:5b88d5760320 1647 * HardwareModuleName ::= SEQUENCE {
kenjiArai 0:5b88d5760320 1648 * hwType OBJECT IDENTIFIER,
kenjiArai 0:5b88d5760320 1649 * hwSerialNum OCTET STRING }
kenjiArai 0:5b88d5760320 1650 *
kenjiArai 0:5b88d5760320 1651 * NOTE: we currently only parse and use otherName of type HwModuleName,
kenjiArai 0:5b88d5760320 1652 * as defined in RFC 4108.
kenjiArai 0:5b88d5760320 1653 */
kenjiArai 0:5b88d5760320 1654 static int x509_get_other_name( const mbedtls_x509_buf *subject_alt_name,
kenjiArai 0:5b88d5760320 1655 mbedtls_x509_san_other_name *other_name )
kenjiArai 0:5b88d5760320 1656 {
kenjiArai 0:5b88d5760320 1657 int ret = 0;
kenjiArai 0:5b88d5760320 1658 size_t len;
kenjiArai 0:5b88d5760320 1659 unsigned char *p = subject_alt_name->p;
kenjiArai 0:5b88d5760320 1660 const unsigned char *end = p + subject_alt_name->len;
kenjiArai 0:5b88d5760320 1661 mbedtls_x509_buf cur_oid;
kenjiArai 0:5b88d5760320 1662
kenjiArai 0:5b88d5760320 1663 if( ( subject_alt_name->tag &
kenjiArai 0:5b88d5760320 1664 ( MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK ) ) !=
kenjiArai 0:5b88d5760320 1665 ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME ) )
kenjiArai 0:5b88d5760320 1666 {
kenjiArai 0:5b88d5760320 1667 /*
kenjiArai 0:5b88d5760320 1668 * The given subject alternative name is not of type "othername".
kenjiArai 0:5b88d5760320 1669 */
kenjiArai 0:5b88d5760320 1670 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
kenjiArai 0:5b88d5760320 1671 }
kenjiArai 0:5b88d5760320 1672
kenjiArai 0:5b88d5760320 1673 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
kenjiArai 0:5b88d5760320 1674 MBEDTLS_ASN1_OID ) ) != 0 )
kenjiArai 0:5b88d5760320 1675 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kenjiArai 0:5b88d5760320 1676
kenjiArai 0:5b88d5760320 1677 cur_oid.tag = MBEDTLS_ASN1_OID;
kenjiArai 0:5b88d5760320 1678 cur_oid.p = p;
kenjiArai 0:5b88d5760320 1679 cur_oid.len = len;
kenjiArai 0:5b88d5760320 1680
kenjiArai 0:5b88d5760320 1681 /*
kenjiArai 0:5b88d5760320 1682 * Only HwModuleName is currently supported.
kenjiArai 0:5b88d5760320 1683 */
kenjiArai 0:5b88d5760320 1684 if( MBEDTLS_OID_CMP( MBEDTLS_OID_ON_HW_MODULE_NAME, &cur_oid ) != 0 )
kenjiArai 0:5b88d5760320 1685 {
kenjiArai 0:5b88d5760320 1686 return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
kenjiArai 0:5b88d5760320 1687 }
kenjiArai 0:5b88d5760320 1688
kenjiArai 0:5b88d5760320 1689 if( p + len >= end )
kenjiArai 0:5b88d5760320 1690 {
kenjiArai 0:5b88d5760320 1691 mbedtls_platform_zeroize( other_name, sizeof( other_name ) );
kenjiArai 0:5b88d5760320 1692 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kenjiArai 0:5b88d5760320 1693 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kenjiArai 0:5b88d5760320 1694 }
kenjiArai 0:5b88d5760320 1695 p += len;
kenjiArai 0:5b88d5760320 1696 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
kenjiArai 0:5b88d5760320 1697 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 )
kenjiArai 0:5b88d5760320 1698 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kenjiArai 0:5b88d5760320 1699
kenjiArai 0:5b88d5760320 1700 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
kenjiArai 0:5b88d5760320 1701 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
kenjiArai 0:5b88d5760320 1702 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kenjiArai 0:5b88d5760320 1703
kenjiArai 0:5b88d5760320 1704 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OID ) ) != 0 )
kenjiArai 0:5b88d5760320 1705 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kenjiArai 0:5b88d5760320 1706
kenjiArai 0:5b88d5760320 1707 other_name->value.hardware_module_name.oid.tag = MBEDTLS_ASN1_OID;
kenjiArai 0:5b88d5760320 1708 other_name->value.hardware_module_name.oid.p = p;
kenjiArai 0:5b88d5760320 1709 other_name->value.hardware_module_name.oid.len = len;
kenjiArai 0:5b88d5760320 1710
kenjiArai 0:5b88d5760320 1711 if( p + len >= end )
kenjiArai 0:5b88d5760320 1712 {
kenjiArai 0:5b88d5760320 1713 mbedtls_platform_zeroize( other_name, sizeof( other_name ) );
kenjiArai 0:5b88d5760320 1714 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kenjiArai 0:5b88d5760320 1715 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kenjiArai 0:5b88d5760320 1716 }
kenjiArai 0:5b88d5760320 1717 p += len;
kenjiArai 0:5b88d5760320 1718 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
kenjiArai 0:5b88d5760320 1719 MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
kenjiArai 0:5b88d5760320 1720 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kenjiArai 0:5b88d5760320 1721
kenjiArai 0:5b88d5760320 1722 other_name->value.hardware_module_name.val.tag = MBEDTLS_ASN1_OCTET_STRING;
kenjiArai 0:5b88d5760320 1723 other_name->value.hardware_module_name.val.p = p;
kenjiArai 0:5b88d5760320 1724 other_name->value.hardware_module_name.val.len = len;
kenjiArai 0:5b88d5760320 1725 p += len;
kenjiArai 0:5b88d5760320 1726 if( p != end )
kenjiArai 0:5b88d5760320 1727 {
kenjiArai 0:5b88d5760320 1728 mbedtls_platform_zeroize( other_name,
kenjiArai 0:5b88d5760320 1729 sizeof( other_name ) );
kenjiArai 0:5b88d5760320 1730 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kenjiArai 0:5b88d5760320 1731 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kenjiArai 0:5b88d5760320 1732 }
kenjiArai 0:5b88d5760320 1733 return( 0 );
kenjiArai 0:5b88d5760320 1734 }
kenjiArai 0:5b88d5760320 1735
kenjiArai 0:5b88d5760320 1736 static int x509_info_subject_alt_name( char **buf, size_t *size,
kenjiArai 0:5b88d5760320 1737 const mbedtls_x509_sequence
kenjiArai 0:5b88d5760320 1738 *subject_alt_name,
kenjiArai 0:5b88d5760320 1739 const char *prefix )
kenjiArai 0:5b88d5760320 1740 {
kenjiArai 0:5b88d5760320 1741 int ret;
kenjiArai 0:5b88d5760320 1742 size_t n = *size;
kenjiArai 0:5b88d5760320 1743 char *p = *buf;
kenjiArai 0:5b88d5760320 1744 const mbedtls_x509_sequence *cur = subject_alt_name;
kenjiArai 0:5b88d5760320 1745 mbedtls_x509_subject_alternative_name san;
kenjiArai 0:5b88d5760320 1746 int parse_ret;
kenjiArai 0:5b88d5760320 1747
kenjiArai 0:5b88d5760320 1748 while( cur != NULL )
kenjiArai 0:5b88d5760320 1749 {
kenjiArai 0:5b88d5760320 1750 memset( &san, 0, sizeof( san ) );
kenjiArai 0:5b88d5760320 1751 parse_ret = mbedtls_x509_parse_subject_alt_name( &cur->buf, &san );
kenjiArai 0:5b88d5760320 1752 if( parse_ret != 0 )
kenjiArai 0:5b88d5760320 1753 {
kenjiArai 0:5b88d5760320 1754 if( parse_ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE )
kenjiArai 0:5b88d5760320 1755 {
kenjiArai 0:5b88d5760320 1756 ret = mbedtls_snprintf( p, n, "\n%s <unsupported>", prefix );
kenjiArai 0:5b88d5760320 1757 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 1758 }
kenjiArai 0:5b88d5760320 1759 else
kenjiArai 0:5b88d5760320 1760 {
kenjiArai 0:5b88d5760320 1761 ret = mbedtls_snprintf( p, n, "\n%s <malformed>", prefix );
kenjiArai 0:5b88d5760320 1762 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 1763 }
kenjiArai 0:5b88d5760320 1764 cur = cur->next;
kenjiArai 0:5b88d5760320 1765 continue;
kenjiArai 0:5b88d5760320 1766 }
kenjiArai 0:5b88d5760320 1767
kenjiArai 0:5b88d5760320 1768 switch( san.type )
kenjiArai 0:5b88d5760320 1769 {
kenjiArai 0:5b88d5760320 1770 /*
kenjiArai 0:5b88d5760320 1771 * otherName
kenjiArai 0:5b88d5760320 1772 */
kenjiArai 0:5b88d5760320 1773 case MBEDTLS_X509_SAN_OTHER_NAME:
kenjiArai 0:5b88d5760320 1774 {
kenjiArai 0:5b88d5760320 1775 mbedtls_x509_san_other_name *other_name = &san.san.other_name;
kenjiArai 0:5b88d5760320 1776
kenjiArai 0:5b88d5760320 1777 ret = mbedtls_snprintf( p, n, "\n%s otherName :", prefix );
kenjiArai 0:5b88d5760320 1778 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 1779
kenjiArai 0:5b88d5760320 1780 if( MBEDTLS_OID_CMP( MBEDTLS_OID_ON_HW_MODULE_NAME,
kenjiArai 0:5b88d5760320 1781 &other_name->value.hardware_module_name.oid ) != 0 )
kenjiArai 0:5b88d5760320 1782 {
kenjiArai 0:5b88d5760320 1783 ret = mbedtls_snprintf( p, n, "\n%s hardware module name :", prefix );
kenjiArai 0:5b88d5760320 1784 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 1785 ret = mbedtls_snprintf( p, n, "\n%s hardware type : ", prefix );
kenjiArai 0:5b88d5760320 1786 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 1787
kenjiArai 0:5b88d5760320 1788 ret = mbedtls_oid_get_numeric_string( p, n, &other_name->value.hardware_module_name.oid );
kenjiArai 0:5b88d5760320 1789 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 1790
kenjiArai 0:5b88d5760320 1791 ret = mbedtls_snprintf( p, n, "\n%s hardware serial number : ", prefix );
kenjiArai 0:5b88d5760320 1792 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 1793
kenjiArai 0:5b88d5760320 1794 if( other_name->value.hardware_module_name.val.len >= n )
kenjiArai 0:5b88d5760320 1795 {
kenjiArai 0:5b88d5760320 1796 *p = '\0';
kenjiArai 0:5b88d5760320 1797 return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
kenjiArai 0:5b88d5760320 1798 }
kenjiArai 0:5b88d5760320 1799
kenjiArai 0:5b88d5760320 1800 memcpy( p, other_name->value.hardware_module_name.val.p,
kenjiArai 0:5b88d5760320 1801 other_name->value.hardware_module_name.val.len );
kenjiArai 0:5b88d5760320 1802 p += other_name->value.hardware_module_name.val.len;
kenjiArai 0:5b88d5760320 1803
kenjiArai 0:5b88d5760320 1804 n -= other_name->value.hardware_module_name.val.len;
kenjiArai 0:5b88d5760320 1805
kenjiArai 0:5b88d5760320 1806 }/* MBEDTLS_OID_ON_HW_MODULE_NAME */
kenjiArai 0:5b88d5760320 1807 }
kenjiArai 0:5b88d5760320 1808 break;
kenjiArai 0:5b88d5760320 1809
kenjiArai 0:5b88d5760320 1810 /*
kenjiArai 0:5b88d5760320 1811 * dNSName
kenjiArai 0:5b88d5760320 1812 */
kenjiArai 0:5b88d5760320 1813 case MBEDTLS_X509_SAN_DNS_NAME:
kenjiArai 0:5b88d5760320 1814 {
kenjiArai 0:5b88d5760320 1815 ret = mbedtls_snprintf( p, n, "\n%s dNSName : ", prefix );
kenjiArai 0:5b88d5760320 1816 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 1817 if( san.san.unstructured_name.len >= n )
kenjiArai 0:5b88d5760320 1818 {
kenjiArai 0:5b88d5760320 1819 *p = '\0';
kenjiArai 0:5b88d5760320 1820 return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
kenjiArai 0:5b88d5760320 1821 }
kenjiArai 0:5b88d5760320 1822
kenjiArai 0:5b88d5760320 1823 memcpy( p, san.san.unstructured_name.p, san.san.unstructured_name.len );
kenjiArai 0:5b88d5760320 1824 p += san.san.unstructured_name.len;
kenjiArai 0:5b88d5760320 1825 n -= san.san.unstructured_name.len;
kenjiArai 0:5b88d5760320 1826 }
kenjiArai 0:5b88d5760320 1827 break;
kenjiArai 0:5b88d5760320 1828
kenjiArai 0:5b88d5760320 1829 /*
kenjiArai 0:5b88d5760320 1830 * Type not supported, skip item.
kenjiArai 0:5b88d5760320 1831 */
kenjiArai 0:5b88d5760320 1832 default:
kenjiArai 0:5b88d5760320 1833 ret = mbedtls_snprintf( p, n, "\n%s <unsupported>", prefix );
kenjiArai 0:5b88d5760320 1834 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 1835 break;
kenjiArai 0:5b88d5760320 1836 }
kenjiArai 0:5b88d5760320 1837
kenjiArai 0:5b88d5760320 1838 cur = cur->next;
kenjiArai 0:5b88d5760320 1839 }
kenjiArai 0:5b88d5760320 1840
kenjiArai 0:5b88d5760320 1841 *p = '\0';
kenjiArai 0:5b88d5760320 1842
kenjiArai 0:5b88d5760320 1843 *size = n;
kenjiArai 0:5b88d5760320 1844 *buf = p;
kenjiArai 0:5b88d5760320 1845
kenjiArai 0:5b88d5760320 1846 return( 0 );
kenjiArai 0:5b88d5760320 1847 }
kenjiArai 0:5b88d5760320 1848
kenjiArai 0:5b88d5760320 1849 int mbedtls_x509_parse_subject_alt_name( const mbedtls_x509_buf *san_buf,
kenjiArai 0:5b88d5760320 1850 mbedtls_x509_subject_alternative_name *san )
kenjiArai 0:5b88d5760320 1851 {
kenjiArai 0:5b88d5760320 1852 int ret;
kenjiArai 0:5b88d5760320 1853 switch( san_buf->tag &
kenjiArai 0:5b88d5760320 1854 ( MBEDTLS_ASN1_TAG_CLASS_MASK |
kenjiArai 0:5b88d5760320 1855 MBEDTLS_ASN1_TAG_VALUE_MASK ) )
kenjiArai 0:5b88d5760320 1856 {
kenjiArai 0:5b88d5760320 1857 /*
kenjiArai 0:5b88d5760320 1858 * otherName
kenjiArai 0:5b88d5760320 1859 */
kenjiArai 0:5b88d5760320 1860 case( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME ):
kenjiArai 0:5b88d5760320 1861 {
kenjiArai 0:5b88d5760320 1862 mbedtls_x509_san_other_name other_name;
kenjiArai 0:5b88d5760320 1863
kenjiArai 0:5b88d5760320 1864 ret = x509_get_other_name( san_buf, &other_name );
kenjiArai 0:5b88d5760320 1865 if( ret != 0 )
kenjiArai 0:5b88d5760320 1866 return( ret );
kenjiArai 0:5b88d5760320 1867
kenjiArai 0:5b88d5760320 1868 memset( san, 0, sizeof( mbedtls_x509_subject_alternative_name ) );
kenjiArai 0:5b88d5760320 1869 san->type = MBEDTLS_X509_SAN_OTHER_NAME;
kenjiArai 0:5b88d5760320 1870 memcpy( &san->san.other_name,
kenjiArai 0:5b88d5760320 1871 &other_name, sizeof( other_name ) );
kenjiArai 0:5b88d5760320 1872
kenjiArai 0:5b88d5760320 1873 }
kenjiArai 0:5b88d5760320 1874 break;
kenjiArai 0:5b88d5760320 1875
kenjiArai 0:5b88d5760320 1876 /*
kenjiArai 0:5b88d5760320 1877 * dNSName
kenjiArai 0:5b88d5760320 1878 */
kenjiArai 0:5b88d5760320 1879 case( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME ):
kenjiArai 0:5b88d5760320 1880 {
kenjiArai 0:5b88d5760320 1881 memset( san, 0, sizeof( mbedtls_x509_subject_alternative_name ) );
kenjiArai 0:5b88d5760320 1882 san->type = MBEDTLS_X509_SAN_DNS_NAME;
kenjiArai 0:5b88d5760320 1883
kenjiArai 0:5b88d5760320 1884 memcpy( &san->san.unstructured_name,
kenjiArai 0:5b88d5760320 1885 san_buf, sizeof( *san_buf ) );
kenjiArai 0:5b88d5760320 1886
kenjiArai 0:5b88d5760320 1887 }
kenjiArai 0:5b88d5760320 1888 break;
kenjiArai 0:5b88d5760320 1889
kenjiArai 0:5b88d5760320 1890 /*
kenjiArai 0:5b88d5760320 1891 * Type not supported
kenjiArai 0:5b88d5760320 1892 */
kenjiArai 0:5b88d5760320 1893 default:
kenjiArai 0:5b88d5760320 1894 return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
kenjiArai 0:5b88d5760320 1895 }
kenjiArai 0:5b88d5760320 1896 return( 0 );
kenjiArai 0:5b88d5760320 1897 }
kenjiArai 0:5b88d5760320 1898
kenjiArai 0:5b88d5760320 1899 #define PRINT_ITEM(i) \
kenjiArai 0:5b88d5760320 1900 { \
kenjiArai 0:5b88d5760320 1901 ret = mbedtls_snprintf( p, n, "%s" i, sep ); \
kenjiArai 0:5b88d5760320 1902 MBEDTLS_X509_SAFE_SNPRINTF; \
kenjiArai 0:5b88d5760320 1903 sep = ", "; \
kenjiArai 0:5b88d5760320 1904 }
kenjiArai 0:5b88d5760320 1905
kenjiArai 0:5b88d5760320 1906 #define CERT_TYPE(type,name) \
kenjiArai 0:5b88d5760320 1907 if( ns_cert_type & (type) ) \
kenjiArai 0:5b88d5760320 1908 PRINT_ITEM( name );
kenjiArai 0:5b88d5760320 1909
kenjiArai 0:5b88d5760320 1910 static int x509_info_cert_type( char **buf, size_t *size,
kenjiArai 0:5b88d5760320 1911 unsigned char ns_cert_type )
kenjiArai 0:5b88d5760320 1912 {
kenjiArai 0:5b88d5760320 1913 int ret;
kenjiArai 0:5b88d5760320 1914 size_t n = *size;
kenjiArai 0:5b88d5760320 1915 char *p = *buf;
kenjiArai 0:5b88d5760320 1916 const char *sep = "";
kenjiArai 0:5b88d5760320 1917
kenjiArai 0:5b88d5760320 1918 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT, "SSL Client" );
kenjiArai 0:5b88d5760320 1919 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER, "SSL Server" );
kenjiArai 0:5b88d5760320 1920 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL, "Email" );
kenjiArai 0:5b88d5760320 1921 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing" );
kenjiArai 0:5b88d5760320 1922 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_RESERVED, "Reserved" );
kenjiArai 0:5b88d5760320 1923 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CA, "SSL CA" );
kenjiArai 0:5b88d5760320 1924 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA, "Email CA" );
kenjiArai 0:5b88d5760320 1925 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA" );
kenjiArai 0:5b88d5760320 1926
kenjiArai 0:5b88d5760320 1927 *size = n;
kenjiArai 0:5b88d5760320 1928 *buf = p;
kenjiArai 0:5b88d5760320 1929
kenjiArai 0:5b88d5760320 1930 return( 0 );
kenjiArai 0:5b88d5760320 1931 }
kenjiArai 0:5b88d5760320 1932
kenjiArai 0:5b88d5760320 1933 #define KEY_USAGE(code,name) \
kenjiArai 0:5b88d5760320 1934 if( key_usage & (code) ) \
kenjiArai 0:5b88d5760320 1935 PRINT_ITEM( name );
kenjiArai 0:5b88d5760320 1936
kenjiArai 0:5b88d5760320 1937 static int x509_info_key_usage( char **buf, size_t *size,
kenjiArai 0:5b88d5760320 1938 unsigned int key_usage )
kenjiArai 0:5b88d5760320 1939 {
kenjiArai 0:5b88d5760320 1940 int ret;
kenjiArai 0:5b88d5760320 1941 size_t n = *size;
kenjiArai 0:5b88d5760320 1942 char *p = *buf;
kenjiArai 0:5b88d5760320 1943 const char *sep = "";
kenjiArai 0:5b88d5760320 1944
kenjiArai 0:5b88d5760320 1945 KEY_USAGE( MBEDTLS_X509_KU_DIGITAL_SIGNATURE, "Digital Signature" );
kenjiArai 0:5b88d5760320 1946 KEY_USAGE( MBEDTLS_X509_KU_NON_REPUDIATION, "Non Repudiation" );
kenjiArai 0:5b88d5760320 1947 KEY_USAGE( MBEDTLS_X509_KU_KEY_ENCIPHERMENT, "Key Encipherment" );
kenjiArai 0:5b88d5760320 1948 KEY_USAGE( MBEDTLS_X509_KU_DATA_ENCIPHERMENT, "Data Encipherment" );
kenjiArai 0:5b88d5760320 1949 KEY_USAGE( MBEDTLS_X509_KU_KEY_AGREEMENT, "Key Agreement" );
kenjiArai 0:5b88d5760320 1950 KEY_USAGE( MBEDTLS_X509_KU_KEY_CERT_SIGN, "Key Cert Sign" );
kenjiArai 0:5b88d5760320 1951 KEY_USAGE( MBEDTLS_X509_KU_CRL_SIGN, "CRL Sign" );
kenjiArai 0:5b88d5760320 1952 KEY_USAGE( MBEDTLS_X509_KU_ENCIPHER_ONLY, "Encipher Only" );
kenjiArai 0:5b88d5760320 1953 KEY_USAGE( MBEDTLS_X509_KU_DECIPHER_ONLY, "Decipher Only" );
kenjiArai 0:5b88d5760320 1954
kenjiArai 0:5b88d5760320 1955 *size = n;
kenjiArai 0:5b88d5760320 1956 *buf = p;
kenjiArai 0:5b88d5760320 1957
kenjiArai 0:5b88d5760320 1958 return( 0 );
kenjiArai 0:5b88d5760320 1959 }
kenjiArai 0:5b88d5760320 1960
kenjiArai 0:5b88d5760320 1961 static int x509_info_ext_key_usage( char **buf, size_t *size,
kenjiArai 0:5b88d5760320 1962 const mbedtls_x509_sequence *extended_key_usage )
kenjiArai 0:5b88d5760320 1963 {
kenjiArai 0:5b88d5760320 1964 int ret;
kenjiArai 0:5b88d5760320 1965 const char *desc;
kenjiArai 0:5b88d5760320 1966 size_t n = *size;
kenjiArai 0:5b88d5760320 1967 char *p = *buf;
kenjiArai 0:5b88d5760320 1968 const mbedtls_x509_sequence *cur = extended_key_usage;
kenjiArai 0:5b88d5760320 1969 const char *sep = "";
kenjiArai 0:5b88d5760320 1970
kenjiArai 0:5b88d5760320 1971 while( cur != NULL )
kenjiArai 0:5b88d5760320 1972 {
kenjiArai 0:5b88d5760320 1973 if( mbedtls_oid_get_extended_key_usage( &cur->buf, &desc ) != 0 )
kenjiArai 0:5b88d5760320 1974 desc = "???";
kenjiArai 0:5b88d5760320 1975
kenjiArai 0:5b88d5760320 1976 ret = mbedtls_snprintf( p, n, "%s%s", sep, desc );
kenjiArai 0:5b88d5760320 1977 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 1978
kenjiArai 0:5b88d5760320 1979 sep = ", ";
kenjiArai 0:5b88d5760320 1980
kenjiArai 0:5b88d5760320 1981 cur = cur->next;
kenjiArai 0:5b88d5760320 1982 }
kenjiArai 0:5b88d5760320 1983
kenjiArai 0:5b88d5760320 1984 *size = n;
kenjiArai 0:5b88d5760320 1985 *buf = p;
kenjiArai 0:5b88d5760320 1986
kenjiArai 0:5b88d5760320 1987 return( 0 );
kenjiArai 0:5b88d5760320 1988 }
kenjiArai 0:5b88d5760320 1989
kenjiArai 0:5b88d5760320 1990 static int x509_info_cert_policies( char **buf, size_t *size,
kenjiArai 0:5b88d5760320 1991 const mbedtls_x509_sequence *certificate_policies )
kenjiArai 0:5b88d5760320 1992 {
kenjiArai 0:5b88d5760320 1993 int ret;
kenjiArai 0:5b88d5760320 1994 const char *desc;
kenjiArai 0:5b88d5760320 1995 size_t n = *size;
kenjiArai 0:5b88d5760320 1996 char *p = *buf;
kenjiArai 0:5b88d5760320 1997 const mbedtls_x509_sequence *cur = certificate_policies;
kenjiArai 0:5b88d5760320 1998 const char *sep = "";
kenjiArai 0:5b88d5760320 1999
kenjiArai 0:5b88d5760320 2000 while( cur != NULL )
kenjiArai 0:5b88d5760320 2001 {
kenjiArai 0:5b88d5760320 2002 if( mbedtls_oid_get_certificate_policies( &cur->buf, &desc ) != 0 )
kenjiArai 0:5b88d5760320 2003 desc = "???";
kenjiArai 0:5b88d5760320 2004
kenjiArai 0:5b88d5760320 2005 ret = mbedtls_snprintf( p, n, "%s%s", sep, desc );
kenjiArai 0:5b88d5760320 2006 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 2007
kenjiArai 0:5b88d5760320 2008 sep = ", ";
kenjiArai 0:5b88d5760320 2009
kenjiArai 0:5b88d5760320 2010 cur = cur->next;
kenjiArai 0:5b88d5760320 2011 }
kenjiArai 0:5b88d5760320 2012
kenjiArai 0:5b88d5760320 2013 *size = n;
kenjiArai 0:5b88d5760320 2014 *buf = p;
kenjiArai 0:5b88d5760320 2015
kenjiArai 0:5b88d5760320 2016 return( 0 );
kenjiArai 0:5b88d5760320 2017 }
kenjiArai 0:5b88d5760320 2018
kenjiArai 0:5b88d5760320 2019 /*
kenjiArai 0:5b88d5760320 2020 * Return an informational string about the certificate.
kenjiArai 0:5b88d5760320 2021 */
kenjiArai 0:5b88d5760320 2022 #define BEFORE_COLON 18
kenjiArai 0:5b88d5760320 2023 #define BC "18"
kenjiArai 0:5b88d5760320 2024 int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix,
kenjiArai 0:5b88d5760320 2025 const mbedtls_x509_crt *crt )
kenjiArai 0:5b88d5760320 2026 {
kenjiArai 0:5b88d5760320 2027 int ret;
kenjiArai 0:5b88d5760320 2028 size_t n;
kenjiArai 0:5b88d5760320 2029 char *p;
kenjiArai 0:5b88d5760320 2030 char key_size_str[BEFORE_COLON];
kenjiArai 0:5b88d5760320 2031
kenjiArai 0:5b88d5760320 2032 p = buf;
kenjiArai 0:5b88d5760320 2033 n = size;
kenjiArai 0:5b88d5760320 2034
kenjiArai 0:5b88d5760320 2035 if( NULL == crt )
kenjiArai 0:5b88d5760320 2036 {
kenjiArai 0:5b88d5760320 2037 ret = mbedtls_snprintf( p, n, "\nCertificate is uninitialised!\n" );
kenjiArai 0:5b88d5760320 2038 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 2039
kenjiArai 0:5b88d5760320 2040 return( (int) ( size - n ) );
kenjiArai 0:5b88d5760320 2041 }
kenjiArai 0:5b88d5760320 2042
kenjiArai 0:5b88d5760320 2043 ret = mbedtls_snprintf( p, n, "%scert. version : %d\n",
kenjiArai 0:5b88d5760320 2044 prefix, crt->version );
kenjiArai 0:5b88d5760320 2045 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 2046 ret = mbedtls_snprintf( p, n, "%sserial number : ",
kenjiArai 0:5b88d5760320 2047 prefix );
kenjiArai 0:5b88d5760320 2048 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 2049
kenjiArai 0:5b88d5760320 2050 ret = mbedtls_x509_serial_gets( p, n, &crt->serial );
kenjiArai 0:5b88d5760320 2051 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 2052
kenjiArai 0:5b88d5760320 2053 ret = mbedtls_snprintf( p, n, "\n%sissuer name : ", prefix );
kenjiArai 0:5b88d5760320 2054 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 2055 ret = mbedtls_x509_dn_gets( p, n, &crt->issuer );
kenjiArai 0:5b88d5760320 2056 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 2057
kenjiArai 0:5b88d5760320 2058 ret = mbedtls_snprintf( p, n, "\n%ssubject name : ", prefix );
kenjiArai 0:5b88d5760320 2059 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 2060 ret = mbedtls_x509_dn_gets( p, n, &crt->subject );
kenjiArai 0:5b88d5760320 2061 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 2062
kenjiArai 0:5b88d5760320 2063 ret = mbedtls_snprintf( p, n, "\n%sissued on : " \
kenjiArai 0:5b88d5760320 2064 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
kenjiArai 0:5b88d5760320 2065 crt->valid_from.year, crt->valid_from.mon,
kenjiArai 0:5b88d5760320 2066 crt->valid_from.day, crt->valid_from.hour,
kenjiArai 0:5b88d5760320 2067 crt->valid_from.min, crt->valid_from.sec );
kenjiArai 0:5b88d5760320 2068 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 2069
kenjiArai 0:5b88d5760320 2070 ret = mbedtls_snprintf( p, n, "\n%sexpires on : " \
kenjiArai 0:5b88d5760320 2071 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
kenjiArai 0:5b88d5760320 2072 crt->valid_to.year, crt->valid_to.mon,
kenjiArai 0:5b88d5760320 2073 crt->valid_to.day, crt->valid_to.hour,
kenjiArai 0:5b88d5760320 2074 crt->valid_to.min, crt->valid_to.sec );
kenjiArai 0:5b88d5760320 2075 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 2076
kenjiArai 0:5b88d5760320 2077 ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix );
kenjiArai 0:5b88d5760320 2078 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 2079
kenjiArai 0:5b88d5760320 2080 ret = mbedtls_x509_sig_alg_gets( p, n, &crt->sig_oid, crt->sig_pk,
kenjiArai 0:5b88d5760320 2081 crt->sig_md, crt->sig_opts );
kenjiArai 0:5b88d5760320 2082 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 2083
kenjiArai 0:5b88d5760320 2084 /* Key size */
kenjiArai 0:5b88d5760320 2085 if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON,
kenjiArai 0:5b88d5760320 2086 mbedtls_pk_get_name( &crt->pk ) ) ) != 0 )
kenjiArai 0:5b88d5760320 2087 {
kenjiArai 0:5b88d5760320 2088 return( ret );
kenjiArai 0:5b88d5760320 2089 }
kenjiArai 0:5b88d5760320 2090
kenjiArai 0:5b88d5760320 2091 ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str,
kenjiArai 0:5b88d5760320 2092 (int) mbedtls_pk_get_bitlen( &crt->pk ) );
kenjiArai 0:5b88d5760320 2093 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 2094
kenjiArai 0:5b88d5760320 2095 /*
kenjiArai 0:5b88d5760320 2096 * Optional extensions
kenjiArai 0:5b88d5760320 2097 */
kenjiArai 0:5b88d5760320 2098
kenjiArai 0:5b88d5760320 2099 if( crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS )
kenjiArai 0:5b88d5760320 2100 {
kenjiArai 0:5b88d5760320 2101 ret = mbedtls_snprintf( p, n, "\n%sbasic constraints : CA=%s", prefix,
kenjiArai 0:5b88d5760320 2102 crt->ca_istrue ? "true" : "false" );
kenjiArai 0:5b88d5760320 2103 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 2104
kenjiArai 0:5b88d5760320 2105 if( crt->max_pathlen > 0 )
kenjiArai 0:5b88d5760320 2106 {
kenjiArai 0:5b88d5760320 2107 ret = mbedtls_snprintf( p, n, ", max_pathlen=%d", crt->max_pathlen - 1 );
kenjiArai 0:5b88d5760320 2108 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 2109 }
kenjiArai 0:5b88d5760320 2110 }
kenjiArai 0:5b88d5760320 2111
kenjiArai 0:5b88d5760320 2112 if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
kenjiArai 0:5b88d5760320 2113 {
kenjiArai 0:5b88d5760320 2114 ret = mbedtls_snprintf( p, n, "\n%ssubject alt name :", prefix );
kenjiArai 0:5b88d5760320 2115 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 2116
kenjiArai 0:5b88d5760320 2117 if( ( ret = x509_info_subject_alt_name( &p, &n,
kenjiArai 0:5b88d5760320 2118 &crt->subject_alt_names,
kenjiArai 0:5b88d5760320 2119 prefix ) ) != 0 )
kenjiArai 0:5b88d5760320 2120 return( ret );
kenjiArai 0:5b88d5760320 2121 }
kenjiArai 0:5b88d5760320 2122
kenjiArai 0:5b88d5760320 2123 if( crt->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE )
kenjiArai 0:5b88d5760320 2124 {
kenjiArai 0:5b88d5760320 2125 ret = mbedtls_snprintf( p, n, "\n%scert. type : ", prefix );
kenjiArai 0:5b88d5760320 2126 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 2127
kenjiArai 0:5b88d5760320 2128 if( ( ret = x509_info_cert_type( &p, &n, crt->ns_cert_type ) ) != 0 )
kenjiArai 0:5b88d5760320 2129 return( ret );
kenjiArai 0:5b88d5760320 2130 }
kenjiArai 0:5b88d5760320 2131
kenjiArai 0:5b88d5760320 2132 if( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE )
kenjiArai 0:5b88d5760320 2133 {
kenjiArai 0:5b88d5760320 2134 ret = mbedtls_snprintf( p, n, "\n%skey usage : ", prefix );
kenjiArai 0:5b88d5760320 2135 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 2136
kenjiArai 0:5b88d5760320 2137 if( ( ret = x509_info_key_usage( &p, &n, crt->key_usage ) ) != 0 )
kenjiArai 0:5b88d5760320 2138 return( ret );
kenjiArai 0:5b88d5760320 2139 }
kenjiArai 0:5b88d5760320 2140
kenjiArai 0:5b88d5760320 2141 if( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE )
kenjiArai 0:5b88d5760320 2142 {
kenjiArai 0:5b88d5760320 2143 ret = mbedtls_snprintf( p, n, "\n%sext key usage : ", prefix );
kenjiArai 0:5b88d5760320 2144 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 2145
kenjiArai 0:5b88d5760320 2146 if( ( ret = x509_info_ext_key_usage( &p, &n,
kenjiArai 0:5b88d5760320 2147 &crt->ext_key_usage ) ) != 0 )
kenjiArai 0:5b88d5760320 2148 return( ret );
kenjiArai 0:5b88d5760320 2149 }
kenjiArai 0:5b88d5760320 2150
kenjiArai 0:5b88d5760320 2151 if( crt->ext_types & MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES )
kenjiArai 0:5b88d5760320 2152 {
kenjiArai 0:5b88d5760320 2153 ret = mbedtls_snprintf( p, n, "\n%scertificate policies : ", prefix );
kenjiArai 0:5b88d5760320 2154 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 2155
kenjiArai 0:5b88d5760320 2156 if( ( ret = x509_info_cert_policies( &p, &n,
kenjiArai 0:5b88d5760320 2157 &crt->certificate_policies ) ) != 0 )
kenjiArai 0:5b88d5760320 2158 return( ret );
kenjiArai 0:5b88d5760320 2159 }
kenjiArai 0:5b88d5760320 2160
kenjiArai 0:5b88d5760320 2161 ret = mbedtls_snprintf( p, n, "\n" );
kenjiArai 0:5b88d5760320 2162 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 2163
kenjiArai 0:5b88d5760320 2164 return( (int) ( size - n ) );
kenjiArai 0:5b88d5760320 2165 }
kenjiArai 0:5b88d5760320 2166
kenjiArai 0:5b88d5760320 2167 struct x509_crt_verify_string {
kenjiArai 0:5b88d5760320 2168 int code;
kenjiArai 0:5b88d5760320 2169 const char *string;
kenjiArai 0:5b88d5760320 2170 };
kenjiArai 0:5b88d5760320 2171
kenjiArai 0:5b88d5760320 2172 static const struct x509_crt_verify_string x509_crt_verify_strings[] = {
kenjiArai 0:5b88d5760320 2173 { MBEDTLS_X509_BADCERT_EXPIRED, "The certificate validity has expired" },
kenjiArai 0:5b88d5760320 2174 { MBEDTLS_X509_BADCERT_REVOKED, "The certificate has been revoked (is on a CRL)" },
kenjiArai 0:5b88d5760320 2175 { MBEDTLS_X509_BADCERT_CN_MISMATCH, "The certificate Common Name (CN) does not match with the expected CN" },
kenjiArai 0:5b88d5760320 2176 { MBEDTLS_X509_BADCERT_NOT_TRUSTED, "The certificate is not correctly signed by the trusted CA" },
kenjiArai 0:5b88d5760320 2177 { MBEDTLS_X509_BADCRL_NOT_TRUSTED, "The CRL is not correctly signed by the trusted CA" },
kenjiArai 0:5b88d5760320 2178 { MBEDTLS_X509_BADCRL_EXPIRED, "The CRL is expired" },
kenjiArai 0:5b88d5760320 2179 { MBEDTLS_X509_BADCERT_MISSING, "Certificate was missing" },
kenjiArai 0:5b88d5760320 2180 { MBEDTLS_X509_BADCERT_SKIP_VERIFY, "Certificate verification was skipped" },
kenjiArai 0:5b88d5760320 2181 { MBEDTLS_X509_BADCERT_OTHER, "Other reason (can be used by verify callback)" },
kenjiArai 0:5b88d5760320 2182 { MBEDTLS_X509_BADCERT_FUTURE, "The certificate validity starts in the future" },
kenjiArai 0:5b88d5760320 2183 { MBEDTLS_X509_BADCRL_FUTURE, "The CRL is from the future" },
kenjiArai 0:5b88d5760320 2184 { MBEDTLS_X509_BADCERT_KEY_USAGE, "Usage does not match the keyUsage extension" },
kenjiArai 0:5b88d5760320 2185 { MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, "Usage does not match the extendedKeyUsage extension" },
kenjiArai 0:5b88d5760320 2186 { MBEDTLS_X509_BADCERT_NS_CERT_TYPE, "Usage does not match the nsCertType extension" },
kenjiArai 0:5b88d5760320 2187 { MBEDTLS_X509_BADCERT_BAD_MD, "The certificate is signed with an unacceptable hash." },
kenjiArai 0:5b88d5760320 2188 { MBEDTLS_X509_BADCERT_BAD_PK, "The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA)." },
kenjiArai 0:5b88d5760320 2189 { MBEDTLS_X509_BADCERT_BAD_KEY, "The certificate is signed with an unacceptable key (eg bad curve, RSA too short)." },
kenjiArai 0:5b88d5760320 2190 { MBEDTLS_X509_BADCRL_BAD_MD, "The CRL is signed with an unacceptable hash." },
kenjiArai 0:5b88d5760320 2191 { MBEDTLS_X509_BADCRL_BAD_PK, "The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA)." },
kenjiArai 0:5b88d5760320 2192 { MBEDTLS_X509_BADCRL_BAD_KEY, "The CRL is signed with an unacceptable key (eg bad curve, RSA too short)." },
kenjiArai 0:5b88d5760320 2193 { 0, NULL }
kenjiArai 0:5b88d5760320 2194 };
kenjiArai 0:5b88d5760320 2195
kenjiArai 0:5b88d5760320 2196 int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix,
kenjiArai 0:5b88d5760320 2197 uint32_t flags )
kenjiArai 0:5b88d5760320 2198 {
kenjiArai 0:5b88d5760320 2199 int ret;
kenjiArai 0:5b88d5760320 2200 const struct x509_crt_verify_string *cur;
kenjiArai 0:5b88d5760320 2201 char *p = buf;
kenjiArai 0:5b88d5760320 2202 size_t n = size;
kenjiArai 0:5b88d5760320 2203
kenjiArai 0:5b88d5760320 2204 for( cur = x509_crt_verify_strings; cur->string != NULL ; cur++ )
kenjiArai 0:5b88d5760320 2205 {
kenjiArai 0:5b88d5760320 2206 if( ( flags & cur->code ) == 0 )
kenjiArai 0:5b88d5760320 2207 continue;
kenjiArai 0:5b88d5760320 2208
kenjiArai 0:5b88d5760320 2209 ret = mbedtls_snprintf( p, n, "%s%s\n", prefix, cur->string );
kenjiArai 0:5b88d5760320 2210 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 2211 flags ^= cur->code;
kenjiArai 0:5b88d5760320 2212 }
kenjiArai 0:5b88d5760320 2213
kenjiArai 0:5b88d5760320 2214 if( flags != 0 )
kenjiArai 0:5b88d5760320 2215 {
kenjiArai 0:5b88d5760320 2216 ret = mbedtls_snprintf( p, n, "%sUnknown reason "
kenjiArai 0:5b88d5760320 2217 "(this should not happen)\n", prefix );
kenjiArai 0:5b88d5760320 2218 MBEDTLS_X509_SAFE_SNPRINTF;
kenjiArai 0:5b88d5760320 2219 }
kenjiArai 0:5b88d5760320 2220
kenjiArai 0:5b88d5760320 2221 return( (int) ( size - n ) );
kenjiArai 0:5b88d5760320 2222 }
kenjiArai 0:5b88d5760320 2223
kenjiArai 0:5b88d5760320 2224 #if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
kenjiArai 0:5b88d5760320 2225 int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt,
kenjiArai 0:5b88d5760320 2226 unsigned int usage )
kenjiArai 0:5b88d5760320 2227 {
kenjiArai 0:5b88d5760320 2228 unsigned int usage_must, usage_may;
kenjiArai 0:5b88d5760320 2229 unsigned int may_mask = MBEDTLS_X509_KU_ENCIPHER_ONLY
kenjiArai 0:5b88d5760320 2230 | MBEDTLS_X509_KU_DECIPHER_ONLY;
kenjiArai 0:5b88d5760320 2231
kenjiArai 0:5b88d5760320 2232 if( ( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) == 0 )
kenjiArai 0:5b88d5760320 2233 return( 0 );
kenjiArai 0:5b88d5760320 2234
kenjiArai 0:5b88d5760320 2235 usage_must = usage & ~may_mask;
kenjiArai 0:5b88d5760320 2236
kenjiArai 0:5b88d5760320 2237 if( ( ( crt->key_usage & ~may_mask ) & usage_must ) != usage_must )
kenjiArai 0:5b88d5760320 2238 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
kenjiArai 0:5b88d5760320 2239
kenjiArai 0:5b88d5760320 2240 usage_may = usage & may_mask;
kenjiArai 0:5b88d5760320 2241
kenjiArai 0:5b88d5760320 2242 if( ( ( crt->key_usage & may_mask ) | usage_may ) != usage_may )
kenjiArai 0:5b88d5760320 2243 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
kenjiArai 0:5b88d5760320 2244
kenjiArai 0:5b88d5760320 2245 return( 0 );
kenjiArai 0:5b88d5760320 2246 }
kenjiArai 0:5b88d5760320 2247 #endif
kenjiArai 0:5b88d5760320 2248
kenjiArai 0:5b88d5760320 2249 #if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE)
kenjiArai 0:5b88d5760320 2250 int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt,
kenjiArai 0:5b88d5760320 2251 const char *usage_oid,
kenjiArai 0:5b88d5760320 2252 size_t usage_len )
kenjiArai 0:5b88d5760320 2253 {
kenjiArai 0:5b88d5760320 2254 const mbedtls_x509_sequence *cur;
kenjiArai 0:5b88d5760320 2255
kenjiArai 0:5b88d5760320 2256 /* Extension is not mandatory, absent means no restriction */
kenjiArai 0:5b88d5760320 2257 if( ( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) == 0 )
kenjiArai 0:5b88d5760320 2258 return( 0 );
kenjiArai 0:5b88d5760320 2259
kenjiArai 0:5b88d5760320 2260 /*
kenjiArai 0:5b88d5760320 2261 * Look for the requested usage (or wildcard ANY) in our list
kenjiArai 0:5b88d5760320 2262 */
kenjiArai 0:5b88d5760320 2263 for( cur = &crt->ext_key_usage; cur != NULL; cur = cur->next )
kenjiArai 0:5b88d5760320 2264 {
kenjiArai 0:5b88d5760320 2265 const mbedtls_x509_buf *cur_oid = &cur->buf;
kenjiArai 0:5b88d5760320 2266
kenjiArai 0:5b88d5760320 2267 if( cur_oid->len == usage_len &&
kenjiArai 0:5b88d5760320 2268 memcmp( cur_oid->p, usage_oid, usage_len ) == 0 )
kenjiArai 0:5b88d5760320 2269 {
kenjiArai 0:5b88d5760320 2270 return( 0 );
kenjiArai 0:5b88d5760320 2271 }
kenjiArai 0:5b88d5760320 2272
kenjiArai 0:5b88d5760320 2273 if( MBEDTLS_OID_CMP( MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE, cur_oid ) == 0 )
kenjiArai 0:5b88d5760320 2274 return( 0 );
kenjiArai 0:5b88d5760320 2275 }
kenjiArai 0:5b88d5760320 2276
kenjiArai 0:5b88d5760320 2277 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
kenjiArai 0:5b88d5760320 2278 }
kenjiArai 0:5b88d5760320 2279 #endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */
kenjiArai 0:5b88d5760320 2280
kenjiArai 0:5b88d5760320 2281 #if defined(MBEDTLS_X509_CRL_PARSE_C)
kenjiArai 0:5b88d5760320 2282 /*
kenjiArai 0:5b88d5760320 2283 * Return 1 if the certificate is revoked, or 0 otherwise.
kenjiArai 0:5b88d5760320 2284 */
kenjiArai 0:5b88d5760320 2285 int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl )
kenjiArai 0:5b88d5760320 2286 {
kenjiArai 0:5b88d5760320 2287 const mbedtls_x509_crl_entry *cur = &crl->entry;
kenjiArai 0:5b88d5760320 2288
kenjiArai 0:5b88d5760320 2289 while( cur != NULL && cur->serial.len != 0 )
kenjiArai 0:5b88d5760320 2290 {
kenjiArai 0:5b88d5760320 2291 if( crt->serial.len == cur->serial.len &&
kenjiArai 0:5b88d5760320 2292 memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 )
kenjiArai 0:5b88d5760320 2293 {
kenjiArai 0:5b88d5760320 2294 if( mbedtls_x509_time_is_past( &cur->revocation_date ) )
kenjiArai 0:5b88d5760320 2295 return( 1 );
kenjiArai 0:5b88d5760320 2296 }
kenjiArai 0:5b88d5760320 2297
kenjiArai 0:5b88d5760320 2298 cur = cur->next;
kenjiArai 0:5b88d5760320 2299 }
kenjiArai 0:5b88d5760320 2300
kenjiArai 0:5b88d5760320 2301 return( 0 );
kenjiArai 0:5b88d5760320 2302 }
kenjiArai 0:5b88d5760320 2303
kenjiArai 0:5b88d5760320 2304 /*
kenjiArai 0:5b88d5760320 2305 * Check that the given certificate is not revoked according to the CRL.
kenjiArai 0:5b88d5760320 2306 * Skip validation if no CRL for the given CA is present.
kenjiArai 0:5b88d5760320 2307 */
kenjiArai 0:5b88d5760320 2308 static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca,
kenjiArai 0:5b88d5760320 2309 mbedtls_x509_crl *crl_list,
kenjiArai 0:5b88d5760320 2310 const mbedtls_x509_crt_profile *profile )
kenjiArai 0:5b88d5760320 2311 {
kenjiArai 0:5b88d5760320 2312 int flags = 0;
kenjiArai 0:5b88d5760320 2313 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
kenjiArai 0:5b88d5760320 2314 const mbedtls_md_info_t *md_info;
kenjiArai 0:5b88d5760320 2315
kenjiArai 0:5b88d5760320 2316 if( ca == NULL )
kenjiArai 0:5b88d5760320 2317 return( flags );
kenjiArai 0:5b88d5760320 2318
kenjiArai 0:5b88d5760320 2319 while( crl_list != NULL )
kenjiArai 0:5b88d5760320 2320 {
kenjiArai 0:5b88d5760320 2321 if( crl_list->version == 0 ||
kenjiArai 0:5b88d5760320 2322 x509_name_cmp( &crl_list->issuer, &ca->subject ) != 0 )
kenjiArai 0:5b88d5760320 2323 {
kenjiArai 0:5b88d5760320 2324 crl_list = crl_list->next;
kenjiArai 0:5b88d5760320 2325 continue;
kenjiArai 0:5b88d5760320 2326 }
kenjiArai 0:5b88d5760320 2327
kenjiArai 0:5b88d5760320 2328 /*
kenjiArai 0:5b88d5760320 2329 * Check if the CA is configured to sign CRLs
kenjiArai 0:5b88d5760320 2330 */
kenjiArai 0:5b88d5760320 2331 #if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
kenjiArai 0:5b88d5760320 2332 if( mbedtls_x509_crt_check_key_usage( ca,
kenjiArai 0:5b88d5760320 2333 MBEDTLS_X509_KU_CRL_SIGN ) != 0 )
kenjiArai 0:5b88d5760320 2334 {
kenjiArai 0:5b88d5760320 2335 flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
kenjiArai 0:5b88d5760320 2336 break;
kenjiArai 0:5b88d5760320 2337 }
kenjiArai 0:5b88d5760320 2338 #endif
kenjiArai 0:5b88d5760320 2339
kenjiArai 0:5b88d5760320 2340 /*
kenjiArai 0:5b88d5760320 2341 * Check if CRL is correctly signed by the trusted CA
kenjiArai 0:5b88d5760320 2342 */
kenjiArai 0:5b88d5760320 2343 if( x509_profile_check_md_alg( profile, crl_list->sig_md ) != 0 )
kenjiArai 0:5b88d5760320 2344 flags |= MBEDTLS_X509_BADCRL_BAD_MD;
kenjiArai 0:5b88d5760320 2345
kenjiArai 0:5b88d5760320 2346 if( x509_profile_check_pk_alg( profile, crl_list->sig_pk ) != 0 )
kenjiArai 0:5b88d5760320 2347 flags |= MBEDTLS_X509_BADCRL_BAD_PK;
kenjiArai 0:5b88d5760320 2348
kenjiArai 0:5b88d5760320 2349 md_info = mbedtls_md_info_from_type( crl_list->sig_md );
kenjiArai 0:5b88d5760320 2350 if( mbedtls_md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ) != 0 )
kenjiArai 0:5b88d5760320 2351 {
kenjiArai 0:5b88d5760320 2352 /* Note: this can't happen except after an internal error */
kenjiArai 0:5b88d5760320 2353 flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
kenjiArai 0:5b88d5760320 2354 break;
kenjiArai 0:5b88d5760320 2355 }
kenjiArai 0:5b88d5760320 2356
kenjiArai 0:5b88d5760320 2357 if( x509_profile_check_key( profile, &ca->pk ) != 0 )
kenjiArai 0:5b88d5760320 2358 flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
kenjiArai 0:5b88d5760320 2359
kenjiArai 0:5b88d5760320 2360 if( mbedtls_pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, &ca->pk,
kenjiArai 0:5b88d5760320 2361 crl_list->sig_md, hash, mbedtls_md_get_size( md_info ),
kenjiArai 0:5b88d5760320 2362 crl_list->sig.p, crl_list->sig.len ) != 0 )
kenjiArai 0:5b88d5760320 2363 {
kenjiArai 0:5b88d5760320 2364 flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
kenjiArai 0:5b88d5760320 2365 break;
kenjiArai 0:5b88d5760320 2366 }
kenjiArai 0:5b88d5760320 2367
kenjiArai 0:5b88d5760320 2368 /*
kenjiArai 0:5b88d5760320 2369 * Check for validity of CRL (Do not drop out)
kenjiArai 0:5b88d5760320 2370 */
kenjiArai 0:5b88d5760320 2371 if( mbedtls_x509_time_is_past( &crl_list->next_update ) )
kenjiArai 0:5b88d5760320 2372 flags |= MBEDTLS_X509_BADCRL_EXPIRED;
kenjiArai 0:5b88d5760320 2373
kenjiArai 0:5b88d5760320 2374 if( mbedtls_x509_time_is_future( &crl_list->this_update ) )
kenjiArai 0:5b88d5760320 2375 flags |= MBEDTLS_X509_BADCRL_FUTURE;
kenjiArai 0:5b88d5760320 2376
kenjiArai 0:5b88d5760320 2377 /*
kenjiArai 0:5b88d5760320 2378 * Check if certificate is revoked
kenjiArai 0:5b88d5760320 2379 */
kenjiArai 0:5b88d5760320 2380 if( mbedtls_x509_crt_is_revoked( crt, crl_list ) )
kenjiArai 0:5b88d5760320 2381 {
kenjiArai 0:5b88d5760320 2382 flags |= MBEDTLS_X509_BADCERT_REVOKED;
kenjiArai 0:5b88d5760320 2383 break;
kenjiArai 0:5b88d5760320 2384 }
kenjiArai 0:5b88d5760320 2385
kenjiArai 0:5b88d5760320 2386 crl_list = crl_list->next;
kenjiArai 0:5b88d5760320 2387 }
kenjiArai 0:5b88d5760320 2388
kenjiArai 0:5b88d5760320 2389 return( flags );
kenjiArai 0:5b88d5760320 2390 }
kenjiArai 0:5b88d5760320 2391 #endif /* MBEDTLS_X509_CRL_PARSE_C */
kenjiArai 0:5b88d5760320 2392
kenjiArai 0:5b88d5760320 2393 /*
kenjiArai 0:5b88d5760320 2394 * Check the signature of a certificate by its parent
kenjiArai 0:5b88d5760320 2395 */
kenjiArai 0:5b88d5760320 2396 static int x509_crt_check_signature( const mbedtls_x509_crt *child,
kenjiArai 0:5b88d5760320 2397 mbedtls_x509_crt *parent,
kenjiArai 0:5b88d5760320 2398 mbedtls_x509_crt_restart_ctx *rs_ctx )
kenjiArai 0:5b88d5760320 2399 {
kenjiArai 0:5b88d5760320 2400 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
kenjiArai 0:5b88d5760320 2401 size_t hash_len;
kenjiArai 0:5b88d5760320 2402 #if !defined(MBEDTLS_USE_PSA_CRYPTO)
kenjiArai 0:5b88d5760320 2403 const mbedtls_md_info_t *md_info;
kenjiArai 0:5b88d5760320 2404 md_info = mbedtls_md_info_from_type( child->sig_md );
kenjiArai 0:5b88d5760320 2405 hash_len = mbedtls_md_get_size( md_info );
kenjiArai 0:5b88d5760320 2406
kenjiArai 0:5b88d5760320 2407 /* Note: hash errors can happen only after an internal error */
kenjiArai 0:5b88d5760320 2408 if( mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ) != 0 )
kenjiArai 0:5b88d5760320 2409 return( -1 );
kenjiArai 0:5b88d5760320 2410 #else
kenjiArai 0:5b88d5760320 2411 psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT;
kenjiArai 0:5b88d5760320 2412 psa_algorithm_t hash_alg = mbedtls_psa_translate_md( child->sig_md );
kenjiArai 0:5b88d5760320 2413
kenjiArai 0:5b88d5760320 2414 if( psa_hash_setup( &hash_operation, hash_alg ) != PSA_SUCCESS )
kenjiArai 0:5b88d5760320 2415 return( -1 );
kenjiArai 0:5b88d5760320 2416
kenjiArai 0:5b88d5760320 2417 if( psa_hash_update( &hash_operation, child->tbs.p, child->tbs.len )
kenjiArai 0:5b88d5760320 2418 != PSA_SUCCESS )
kenjiArai 0:5b88d5760320 2419 {
kenjiArai 0:5b88d5760320 2420 return( -1 );
kenjiArai 0:5b88d5760320 2421 }
kenjiArai 0:5b88d5760320 2422
kenjiArai 0:5b88d5760320 2423 if( psa_hash_finish( &hash_operation, hash, sizeof( hash ), &hash_len )
kenjiArai 0:5b88d5760320 2424 != PSA_SUCCESS )
kenjiArai 0:5b88d5760320 2425 {
kenjiArai 0:5b88d5760320 2426 return( -1 );
kenjiArai 0:5b88d5760320 2427 }
kenjiArai 0:5b88d5760320 2428 #endif /* MBEDTLS_USE_PSA_CRYPTO */
kenjiArai 0:5b88d5760320 2429 /* Skip expensive computation on obvious mismatch */
kenjiArai 0:5b88d5760320 2430 if( ! mbedtls_pk_can_do( &parent->pk, child->sig_pk ) )
kenjiArai 0:5b88d5760320 2431 return( -1 );
kenjiArai 0:5b88d5760320 2432
kenjiArai 0:5b88d5760320 2433 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
kenjiArai 0:5b88d5760320 2434 if( rs_ctx != NULL && child->sig_pk == MBEDTLS_PK_ECDSA )
kenjiArai 0:5b88d5760320 2435 {
kenjiArai 0:5b88d5760320 2436 return( mbedtls_pk_verify_restartable( &parent->pk,
kenjiArai 0:5b88d5760320 2437 child->sig_md, hash, hash_len,
kenjiArai 0:5b88d5760320 2438 child->sig.p, child->sig.len, &rs_ctx->pk ) );
kenjiArai 0:5b88d5760320 2439 }
kenjiArai 0:5b88d5760320 2440 #else
kenjiArai 0:5b88d5760320 2441 (void) rs_ctx;
kenjiArai 0:5b88d5760320 2442 #endif
kenjiArai 0:5b88d5760320 2443
kenjiArai 0:5b88d5760320 2444 return( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk,
kenjiArai 0:5b88d5760320 2445 child->sig_md, hash, hash_len,
kenjiArai 0:5b88d5760320 2446 child->sig.p, child->sig.len ) );
kenjiArai 0:5b88d5760320 2447 }
kenjiArai 0:5b88d5760320 2448
kenjiArai 0:5b88d5760320 2449 /*
kenjiArai 0:5b88d5760320 2450 * Check if 'parent' is a suitable parent (signing CA) for 'child'.
kenjiArai 0:5b88d5760320 2451 * Return 0 if yes, -1 if not.
kenjiArai 0:5b88d5760320 2452 *
kenjiArai 0:5b88d5760320 2453 * top means parent is a locally-trusted certificate
kenjiArai 0:5b88d5760320 2454 */
kenjiArai 0:5b88d5760320 2455 static int x509_crt_check_parent( const mbedtls_x509_crt *child,
kenjiArai 0:5b88d5760320 2456 const mbedtls_x509_crt *parent,
kenjiArai 0:5b88d5760320 2457 int top )
kenjiArai 0:5b88d5760320 2458 {
kenjiArai 0:5b88d5760320 2459 int need_ca_bit;
kenjiArai 0:5b88d5760320 2460
kenjiArai 0:5b88d5760320 2461 /* Parent must be the issuer */
kenjiArai 0:5b88d5760320 2462 if( x509_name_cmp( &child->issuer, &parent->subject ) != 0 )
kenjiArai 0:5b88d5760320 2463 return( -1 );
kenjiArai 0:5b88d5760320 2464
kenjiArai 0:5b88d5760320 2465 /* Parent must have the basicConstraints CA bit set as a general rule */
kenjiArai 0:5b88d5760320 2466 need_ca_bit = 1;
kenjiArai 0:5b88d5760320 2467
kenjiArai 0:5b88d5760320 2468 /* Exception: v1/v2 certificates that are locally trusted. */
kenjiArai 0:5b88d5760320 2469 if( top && parent->version < 3 )
kenjiArai 0:5b88d5760320 2470 need_ca_bit = 0;
kenjiArai 0:5b88d5760320 2471
kenjiArai 0:5b88d5760320 2472 if( need_ca_bit && ! parent->ca_istrue )
kenjiArai 0:5b88d5760320 2473 return( -1 );
kenjiArai 0:5b88d5760320 2474
kenjiArai 0:5b88d5760320 2475 #if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
kenjiArai 0:5b88d5760320 2476 if( need_ca_bit &&
kenjiArai 0:5b88d5760320 2477 mbedtls_x509_crt_check_key_usage( parent, MBEDTLS_X509_KU_KEY_CERT_SIGN ) != 0 )
kenjiArai 0:5b88d5760320 2478 {
kenjiArai 0:5b88d5760320 2479 return( -1 );
kenjiArai 0:5b88d5760320 2480 }
kenjiArai 0:5b88d5760320 2481 #endif
kenjiArai 0:5b88d5760320 2482
kenjiArai 0:5b88d5760320 2483 return( 0 );
kenjiArai 0:5b88d5760320 2484 }
kenjiArai 0:5b88d5760320 2485
kenjiArai 0:5b88d5760320 2486 /*
kenjiArai 0:5b88d5760320 2487 * Find a suitable parent for child in candidates, or return NULL.
kenjiArai 0:5b88d5760320 2488 *
kenjiArai 0:5b88d5760320 2489 * Here suitable is defined as:
kenjiArai 0:5b88d5760320 2490 * 1. subject name matches child's issuer
kenjiArai 0:5b88d5760320 2491 * 2. if necessary, the CA bit is set and key usage allows signing certs
kenjiArai 0:5b88d5760320 2492 * 3. for trusted roots, the signature is correct
kenjiArai 0:5b88d5760320 2493 * (for intermediates, the signature is checked and the result reported)
kenjiArai 0:5b88d5760320 2494 * 4. pathlen constraints are satisfied
kenjiArai 0:5b88d5760320 2495 *
kenjiArai 0:5b88d5760320 2496 * If there's a suitable candidate which is also time-valid, return the first
kenjiArai 0:5b88d5760320 2497 * such. Otherwise, return the first suitable candidate (or NULL if there is
kenjiArai 0:5b88d5760320 2498 * none).
kenjiArai 0:5b88d5760320 2499 *
kenjiArai 0:5b88d5760320 2500 * The rationale for this rule is that someone could have a list of trusted
kenjiArai 0:5b88d5760320 2501 * roots with two versions on the same root with different validity periods.
kenjiArai 0:5b88d5760320 2502 * (At least one user reported having such a list and wanted it to just work.)
kenjiArai 0:5b88d5760320 2503 * The reason we don't just require time-validity is that generally there is
kenjiArai 0:5b88d5760320 2504 * only one version, and if it's expired we want the flags to state that
kenjiArai 0:5b88d5760320 2505 * rather than NOT_TRUSTED, as would be the case if we required it here.
kenjiArai 0:5b88d5760320 2506 *
kenjiArai 0:5b88d5760320 2507 * The rationale for rule 3 (signature for trusted roots) is that users might
kenjiArai 0:5b88d5760320 2508 * have two versions of the same CA with different keys in their list, and the
kenjiArai 0:5b88d5760320 2509 * way we select the correct one is by checking the signature (as we don't
kenjiArai 0:5b88d5760320 2510 * rely on key identifier extensions). (This is one way users might choose to
kenjiArai 0:5b88d5760320 2511 * handle key rollover, another relies on self-issued certs, see [SIRO].)
kenjiArai 0:5b88d5760320 2512 *
kenjiArai 0:5b88d5760320 2513 * Arguments:
kenjiArai 0:5b88d5760320 2514 * - [in] child: certificate for which we're looking for a parent
kenjiArai 0:5b88d5760320 2515 * - [in] candidates: chained list of potential parents
kenjiArai 0:5b88d5760320 2516 * - [out] r_parent: parent found (or NULL)
kenjiArai 0:5b88d5760320 2517 * - [out] r_signature_is_good: 1 if child signature by parent is valid, or 0
kenjiArai 0:5b88d5760320 2518 * - [in] top: 1 if candidates consists of trusted roots, ie we're at the top
kenjiArai 0:5b88d5760320 2519 * of the chain, 0 otherwise
kenjiArai 0:5b88d5760320 2520 * - [in] path_cnt: number of intermediates seen so far
kenjiArai 0:5b88d5760320 2521 * - [in] self_cnt: number of self-signed intermediates seen so far
kenjiArai 0:5b88d5760320 2522 * (will never be greater than path_cnt)
kenjiArai 0:5b88d5760320 2523 * - [in-out] rs_ctx: context for restarting operations
kenjiArai 0:5b88d5760320 2524 *
kenjiArai 0:5b88d5760320 2525 * Return value:
kenjiArai 0:5b88d5760320 2526 * - 0 on success
kenjiArai 0:5b88d5760320 2527 * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise
kenjiArai 0:5b88d5760320 2528 */
kenjiArai 0:5b88d5760320 2529 static int x509_crt_find_parent_in(
kenjiArai 0:5b88d5760320 2530 mbedtls_x509_crt *child,
kenjiArai 0:5b88d5760320 2531 mbedtls_x509_crt *candidates,
kenjiArai 0:5b88d5760320 2532 mbedtls_x509_crt **r_parent,
kenjiArai 0:5b88d5760320 2533 int *r_signature_is_good,
kenjiArai 0:5b88d5760320 2534 int top,
kenjiArai 0:5b88d5760320 2535 unsigned path_cnt,
kenjiArai 0:5b88d5760320 2536 unsigned self_cnt,
kenjiArai 0:5b88d5760320 2537 mbedtls_x509_crt_restart_ctx *rs_ctx )
kenjiArai 0:5b88d5760320 2538 {
kenjiArai 0:5b88d5760320 2539 int ret;
kenjiArai 0:5b88d5760320 2540 mbedtls_x509_crt *parent, *fallback_parent;
kenjiArai 0:5b88d5760320 2541 int signature_is_good, fallback_signature_is_good;
kenjiArai 0:5b88d5760320 2542
kenjiArai 0:5b88d5760320 2543 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
kenjiArai 0:5b88d5760320 2544 /* did we have something in progress? */
kenjiArai 0:5b88d5760320 2545 if( rs_ctx != NULL && rs_ctx->parent != NULL )
kenjiArai 0:5b88d5760320 2546 {
kenjiArai 0:5b88d5760320 2547 /* restore saved state */
kenjiArai 0:5b88d5760320 2548 parent = rs_ctx->parent;
kenjiArai 0:5b88d5760320 2549 fallback_parent = rs_ctx->fallback_parent;
kenjiArai 0:5b88d5760320 2550 fallback_signature_is_good = rs_ctx->fallback_signature_is_good;
kenjiArai 0:5b88d5760320 2551
kenjiArai 0:5b88d5760320 2552 /* clear saved state */
kenjiArai 0:5b88d5760320 2553 rs_ctx->parent = NULL;
kenjiArai 0:5b88d5760320 2554 rs_ctx->fallback_parent = NULL;
kenjiArai 0:5b88d5760320 2555 rs_ctx->fallback_signature_is_good = 0;
kenjiArai 0:5b88d5760320 2556
kenjiArai 0:5b88d5760320 2557 /* resume where we left */
kenjiArai 0:5b88d5760320 2558 goto check_signature;
kenjiArai 0:5b88d5760320 2559 }
kenjiArai 0:5b88d5760320 2560 #endif
kenjiArai 0:5b88d5760320 2561
kenjiArai 0:5b88d5760320 2562 fallback_parent = NULL;
kenjiArai 0:5b88d5760320 2563 fallback_signature_is_good = 0;
kenjiArai 0:5b88d5760320 2564
kenjiArai 0:5b88d5760320 2565 for( parent = candidates; parent != NULL; parent = parent->next )
kenjiArai 0:5b88d5760320 2566 {
kenjiArai 0:5b88d5760320 2567 /* basic parenting skills (name, CA bit, key usage) */
kenjiArai 0:5b88d5760320 2568 if( x509_crt_check_parent( child, parent, top ) != 0 )
kenjiArai 0:5b88d5760320 2569 continue;
kenjiArai 0:5b88d5760320 2570
kenjiArai 0:5b88d5760320 2571 /* +1 because stored max_pathlen is 1 higher that the actual value */
kenjiArai 0:5b88d5760320 2572 if( parent->max_pathlen > 0 &&
kenjiArai 0:5b88d5760320 2573 (size_t) parent->max_pathlen < 1 + path_cnt - self_cnt )
kenjiArai 0:5b88d5760320 2574 {
kenjiArai 0:5b88d5760320 2575 continue;
kenjiArai 0:5b88d5760320 2576 }
kenjiArai 0:5b88d5760320 2577
kenjiArai 0:5b88d5760320 2578 /* Signature */
kenjiArai 0:5b88d5760320 2579 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
kenjiArai 0:5b88d5760320 2580 check_signature:
kenjiArai 0:5b88d5760320 2581 #endif
kenjiArai 0:5b88d5760320 2582 ret = x509_crt_check_signature( child, parent, rs_ctx );
kenjiArai 0:5b88d5760320 2583
kenjiArai 0:5b88d5760320 2584 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
kenjiArai 0:5b88d5760320 2585 if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
kenjiArai 0:5b88d5760320 2586 {
kenjiArai 0:5b88d5760320 2587 /* save state */
kenjiArai 0:5b88d5760320 2588 rs_ctx->parent = parent;
kenjiArai 0:5b88d5760320 2589 rs_ctx->fallback_parent = fallback_parent;
kenjiArai 0:5b88d5760320 2590 rs_ctx->fallback_signature_is_good = fallback_signature_is_good;
kenjiArai 0:5b88d5760320 2591
kenjiArai 0:5b88d5760320 2592 return( ret );
kenjiArai 0:5b88d5760320 2593 }
kenjiArai 0:5b88d5760320 2594 #else
kenjiArai 0:5b88d5760320 2595 (void) ret;
kenjiArai 0:5b88d5760320 2596 #endif
kenjiArai 0:5b88d5760320 2597
kenjiArai 0:5b88d5760320 2598 signature_is_good = ret == 0;
kenjiArai 0:5b88d5760320 2599 if( top && ! signature_is_good )
kenjiArai 0:5b88d5760320 2600 continue;
kenjiArai 0:5b88d5760320 2601
kenjiArai 0:5b88d5760320 2602 /* optional time check */
kenjiArai 0:5b88d5760320 2603 if( mbedtls_x509_time_is_past( &parent->valid_to ) ||
kenjiArai 0:5b88d5760320 2604 mbedtls_x509_time_is_future( &parent->valid_from ) )
kenjiArai 0:5b88d5760320 2605 {
kenjiArai 0:5b88d5760320 2606 if( fallback_parent == NULL )
kenjiArai 0:5b88d5760320 2607 {
kenjiArai 0:5b88d5760320 2608 fallback_parent = parent;
kenjiArai 0:5b88d5760320 2609 fallback_signature_is_good = signature_is_good;
kenjiArai 0:5b88d5760320 2610 }
kenjiArai 0:5b88d5760320 2611
kenjiArai 0:5b88d5760320 2612 continue;
kenjiArai 0:5b88d5760320 2613 }
kenjiArai 0:5b88d5760320 2614
kenjiArai 0:5b88d5760320 2615 break;
kenjiArai 0:5b88d5760320 2616 }
kenjiArai 0:5b88d5760320 2617
kenjiArai 0:5b88d5760320 2618 if( parent != NULL )
kenjiArai 0:5b88d5760320 2619 {
kenjiArai 0:5b88d5760320 2620 *r_parent = parent;
kenjiArai 0:5b88d5760320 2621 *r_signature_is_good = signature_is_good;
kenjiArai 0:5b88d5760320 2622 }
kenjiArai 0:5b88d5760320 2623 else
kenjiArai 0:5b88d5760320 2624 {
kenjiArai 0:5b88d5760320 2625 *r_parent = fallback_parent;
kenjiArai 0:5b88d5760320 2626 *r_signature_is_good = fallback_signature_is_good;
kenjiArai 0:5b88d5760320 2627 }
kenjiArai 0:5b88d5760320 2628
kenjiArai 0:5b88d5760320 2629 return( 0 );
kenjiArai 0:5b88d5760320 2630 }
kenjiArai 0:5b88d5760320 2631
kenjiArai 0:5b88d5760320 2632 /*
kenjiArai 0:5b88d5760320 2633 * Find a parent in trusted CAs or the provided chain, or return NULL.
kenjiArai 0:5b88d5760320 2634 *
kenjiArai 0:5b88d5760320 2635 * Searches in trusted CAs first, and return the first suitable parent found
kenjiArai 0:5b88d5760320 2636 * (see find_parent_in() for definition of suitable).
kenjiArai 0:5b88d5760320 2637 *
kenjiArai 0:5b88d5760320 2638 * Arguments:
kenjiArai 0:5b88d5760320 2639 * - [in] child: certificate for which we're looking for a parent, followed
kenjiArai 0:5b88d5760320 2640 * by a chain of possible intermediates
kenjiArai 0:5b88d5760320 2641 * - [in] trust_ca: list of locally trusted certificates
kenjiArai 0:5b88d5760320 2642 * - [out] parent: parent found (or NULL)
kenjiArai 0:5b88d5760320 2643 * - [out] parent_is_trusted: 1 if returned `parent` is trusted, or 0
kenjiArai 0:5b88d5760320 2644 * - [out] signature_is_good: 1 if child signature by parent is valid, or 0
kenjiArai 0:5b88d5760320 2645 * - [in] path_cnt: number of links in the chain so far (EE -> ... -> child)
kenjiArai 0:5b88d5760320 2646 * - [in] self_cnt: number of self-signed certs in the chain so far
kenjiArai 0:5b88d5760320 2647 * (will always be no greater than path_cnt)
kenjiArai 0:5b88d5760320 2648 * - [in-out] rs_ctx: context for restarting operations
kenjiArai 0:5b88d5760320 2649 *
kenjiArai 0:5b88d5760320 2650 * Return value:
kenjiArai 0:5b88d5760320 2651 * - 0 on success
kenjiArai 0:5b88d5760320 2652 * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise
kenjiArai 0:5b88d5760320 2653 */
kenjiArai 0:5b88d5760320 2654 static int x509_crt_find_parent(
kenjiArai 0:5b88d5760320 2655 mbedtls_x509_crt *child,
kenjiArai 0:5b88d5760320 2656 mbedtls_x509_crt *trust_ca,
kenjiArai 0:5b88d5760320 2657 mbedtls_x509_crt **parent,
kenjiArai 0:5b88d5760320 2658 int *parent_is_trusted,
kenjiArai 0:5b88d5760320 2659 int *signature_is_good,
kenjiArai 0:5b88d5760320 2660 unsigned path_cnt,
kenjiArai 0:5b88d5760320 2661 unsigned self_cnt,
kenjiArai 0:5b88d5760320 2662 mbedtls_x509_crt_restart_ctx *rs_ctx )
kenjiArai 0:5b88d5760320 2663 {
kenjiArai 0:5b88d5760320 2664 int ret;
kenjiArai 0:5b88d5760320 2665 mbedtls_x509_crt *search_list;
kenjiArai 0:5b88d5760320 2666
kenjiArai 0:5b88d5760320 2667 *parent_is_trusted = 1;
kenjiArai 0:5b88d5760320 2668
kenjiArai 0:5b88d5760320 2669 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
kenjiArai 0:5b88d5760320 2670 /* restore then clear saved state if we have some stored */
kenjiArai 0:5b88d5760320 2671 if( rs_ctx != NULL && rs_ctx->parent_is_trusted != -1 )
kenjiArai 0:5b88d5760320 2672 {
kenjiArai 0:5b88d5760320 2673 *parent_is_trusted = rs_ctx->parent_is_trusted;
kenjiArai 0:5b88d5760320 2674 rs_ctx->parent_is_trusted = -1;
kenjiArai 0:5b88d5760320 2675 }
kenjiArai 0:5b88d5760320 2676 #endif
kenjiArai 0:5b88d5760320 2677
kenjiArai 0:5b88d5760320 2678 while( 1 ) {
kenjiArai 0:5b88d5760320 2679 search_list = *parent_is_trusted ? trust_ca : child->next;
kenjiArai 0:5b88d5760320 2680
kenjiArai 0:5b88d5760320 2681 ret = x509_crt_find_parent_in( child, search_list,
kenjiArai 0:5b88d5760320 2682 parent, signature_is_good,
kenjiArai 0:5b88d5760320 2683 *parent_is_trusted,
kenjiArai 0:5b88d5760320 2684 path_cnt, self_cnt, rs_ctx );
kenjiArai 0:5b88d5760320 2685
kenjiArai 0:5b88d5760320 2686 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
kenjiArai 0:5b88d5760320 2687 if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
kenjiArai 0:5b88d5760320 2688 {
kenjiArai 0:5b88d5760320 2689 /* save state */
kenjiArai 0:5b88d5760320 2690 rs_ctx->parent_is_trusted = *parent_is_trusted;
kenjiArai 0:5b88d5760320 2691 return( ret );
kenjiArai 0:5b88d5760320 2692 }
kenjiArai 0:5b88d5760320 2693 #else
kenjiArai 0:5b88d5760320 2694 (void) ret;
kenjiArai 0:5b88d5760320 2695 #endif
kenjiArai 0:5b88d5760320 2696
kenjiArai 0:5b88d5760320 2697 /* stop here if found or already in second iteration */
kenjiArai 0:5b88d5760320 2698 if( *parent != NULL || *parent_is_trusted == 0 )
kenjiArai 0:5b88d5760320 2699 break;
kenjiArai 0:5b88d5760320 2700
kenjiArai 0:5b88d5760320 2701 /* prepare second iteration */
kenjiArai 0:5b88d5760320 2702 *parent_is_trusted = 0;
kenjiArai 0:5b88d5760320 2703 }
kenjiArai 0:5b88d5760320 2704
kenjiArai 0:5b88d5760320 2705 /* extra precaution against mistakes in the caller */
kenjiArai 0:5b88d5760320 2706 if( *parent == NULL )
kenjiArai 0:5b88d5760320 2707 {
kenjiArai 0:5b88d5760320 2708 *parent_is_trusted = 0;
kenjiArai 0:5b88d5760320 2709 *signature_is_good = 0;
kenjiArai 0:5b88d5760320 2710 }
kenjiArai 0:5b88d5760320 2711
kenjiArai 0:5b88d5760320 2712 return( 0 );
kenjiArai 0:5b88d5760320 2713 }
kenjiArai 0:5b88d5760320 2714
kenjiArai 0:5b88d5760320 2715 /*
kenjiArai 0:5b88d5760320 2716 * Check if an end-entity certificate is locally trusted
kenjiArai 0:5b88d5760320 2717 *
kenjiArai 0:5b88d5760320 2718 * Currently we require such certificates to be self-signed (actually only
kenjiArai 0:5b88d5760320 2719 * check for self-issued as self-signatures are not checked)
kenjiArai 0:5b88d5760320 2720 */
kenjiArai 0:5b88d5760320 2721 static int x509_crt_check_ee_locally_trusted(
kenjiArai 0:5b88d5760320 2722 mbedtls_x509_crt *crt,
kenjiArai 0:5b88d5760320 2723 mbedtls_x509_crt *trust_ca )
kenjiArai 0:5b88d5760320 2724 {
kenjiArai 0:5b88d5760320 2725 mbedtls_x509_crt *cur;
kenjiArai 0:5b88d5760320 2726
kenjiArai 0:5b88d5760320 2727 /* must be self-issued */
kenjiArai 0:5b88d5760320 2728 if( x509_name_cmp( &crt->issuer, &crt->subject ) != 0 )
kenjiArai 0:5b88d5760320 2729 return( -1 );
kenjiArai 0:5b88d5760320 2730
kenjiArai 0:5b88d5760320 2731 /* look for an exact match with trusted cert */
kenjiArai 0:5b88d5760320 2732 for( cur = trust_ca; cur != NULL; cur = cur->next )
kenjiArai 0:5b88d5760320 2733 {
kenjiArai 0:5b88d5760320 2734 if( crt->raw.len == cur->raw.len &&
kenjiArai 0:5b88d5760320 2735 memcmp( crt->raw.p, cur->raw.p, crt->raw.len ) == 0 )
kenjiArai 0:5b88d5760320 2736 {
kenjiArai 0:5b88d5760320 2737 return( 0 );
kenjiArai 0:5b88d5760320 2738 }
kenjiArai 0:5b88d5760320 2739 }
kenjiArai 0:5b88d5760320 2740
kenjiArai 0:5b88d5760320 2741 /* too bad */
kenjiArai 0:5b88d5760320 2742 return( -1 );
kenjiArai 0:5b88d5760320 2743 }
kenjiArai 0:5b88d5760320 2744
kenjiArai 0:5b88d5760320 2745 /*
kenjiArai 0:5b88d5760320 2746 * Build and verify a certificate chain
kenjiArai 0:5b88d5760320 2747 *
kenjiArai 0:5b88d5760320 2748 * Given a peer-provided list of certificates EE, C1, ..., Cn and
kenjiArai 0:5b88d5760320 2749 * a list of trusted certs R1, ... Rp, try to build and verify a chain
kenjiArai 0:5b88d5760320 2750 * EE, Ci1, ... Ciq [, Rj]
kenjiArai 0:5b88d5760320 2751 * such that every cert in the chain is a child of the next one,
kenjiArai 0:5b88d5760320 2752 * jumping to a trusted root as early as possible.
kenjiArai 0:5b88d5760320 2753 *
kenjiArai 0:5b88d5760320 2754 * Verify that chain and return it with flags for all issues found.
kenjiArai 0:5b88d5760320 2755 *
kenjiArai 0:5b88d5760320 2756 * Special cases:
kenjiArai 0:5b88d5760320 2757 * - EE == Rj -> return a one-element list containing it
kenjiArai 0:5b88d5760320 2758 * - EE, Ci1, ..., Ciq cannot be continued with a trusted root
kenjiArai 0:5b88d5760320 2759 * -> return that chain with NOT_TRUSTED set on Ciq
kenjiArai 0:5b88d5760320 2760 *
kenjiArai 0:5b88d5760320 2761 * Tests for (aspects of) this function should include at least:
kenjiArai 0:5b88d5760320 2762 * - trusted EE
kenjiArai 0:5b88d5760320 2763 * - EE -> trusted root
kenjiArai 0:5b88d5760320 2764 * - EE -> intermediate CA -> trusted root
kenjiArai 0:5b88d5760320 2765 * - if relevant: EE untrusted
kenjiArai 0:5b88d5760320 2766 * - if relevant: EE -> intermediate, untrusted
kenjiArai 0:5b88d5760320 2767 * with the aspect under test checked at each relevant level (EE, int, root).
kenjiArai 0:5b88d5760320 2768 * For some aspects longer chains are required, but usually length 2 is
kenjiArai 0:5b88d5760320 2769 * enough (but length 1 is not in general).
kenjiArai 0:5b88d5760320 2770 *
kenjiArai 0:5b88d5760320 2771 * Arguments:
kenjiArai 0:5b88d5760320 2772 * - [in] crt: the cert list EE, C1, ..., Cn
kenjiArai 0:5b88d5760320 2773 * - [in] trust_ca: the trusted list R1, ..., Rp
kenjiArai 0:5b88d5760320 2774 * - [in] ca_crl, profile: as in verify_with_profile()
kenjiArai 0:5b88d5760320 2775 * - [out] ver_chain: the built and verified chain
kenjiArai 0:5b88d5760320 2776 * Only valid when return value is 0, may contain garbage otherwise!
kenjiArai 0:5b88d5760320 2777 * Restart note: need not be the same when calling again to resume.
kenjiArai 0:5b88d5760320 2778 * - [in-out] rs_ctx: context for restarting operations
kenjiArai 0:5b88d5760320 2779 *
kenjiArai 0:5b88d5760320 2780 * Return value:
kenjiArai 0:5b88d5760320 2781 * - non-zero if the chain could not be fully built and examined
kenjiArai 0:5b88d5760320 2782 * - 0 is the chain was successfully built and examined,
kenjiArai 0:5b88d5760320 2783 * even if it was found to be invalid
kenjiArai 0:5b88d5760320 2784 */
kenjiArai 0:5b88d5760320 2785 static int x509_crt_verify_chain(
kenjiArai 0:5b88d5760320 2786 mbedtls_x509_crt *crt,
kenjiArai 0:5b88d5760320 2787 mbedtls_x509_crt *trust_ca,
kenjiArai 0:5b88d5760320 2788 mbedtls_x509_crl *ca_crl,
kenjiArai 0:5b88d5760320 2789 mbedtls_x509_crt_ca_cb_t f_ca_cb,
kenjiArai 0:5b88d5760320 2790 void *p_ca_cb,
kenjiArai 0:5b88d5760320 2791 const mbedtls_x509_crt_profile *profile,
kenjiArai 0:5b88d5760320 2792 mbedtls_x509_crt_verify_chain *ver_chain,
kenjiArai 0:5b88d5760320 2793 mbedtls_x509_crt_restart_ctx *rs_ctx )
kenjiArai 0:5b88d5760320 2794 {
kenjiArai 0:5b88d5760320 2795 /* Don't initialize any of those variables here, so that the compiler can
kenjiArai 0:5b88d5760320 2796 * catch potential issues with jumping ahead when restarting */
kenjiArai 0:5b88d5760320 2797 int ret;
kenjiArai 0:5b88d5760320 2798 uint32_t *flags;
kenjiArai 0:5b88d5760320 2799 mbedtls_x509_crt_verify_chain_item *cur;
kenjiArai 0:5b88d5760320 2800 mbedtls_x509_crt *child;
kenjiArai 0:5b88d5760320 2801 mbedtls_x509_crt *parent;
kenjiArai 0:5b88d5760320 2802 int parent_is_trusted;
kenjiArai 0:5b88d5760320 2803 int child_is_trusted;
kenjiArai 0:5b88d5760320 2804 int signature_is_good;
kenjiArai 0:5b88d5760320 2805 unsigned self_cnt;
kenjiArai 0:5b88d5760320 2806 mbedtls_x509_crt *cur_trust_ca = NULL;
kenjiArai 0:5b88d5760320 2807
kenjiArai 0:5b88d5760320 2808 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
kenjiArai 0:5b88d5760320 2809 /* resume if we had an operation in progress */
kenjiArai 0:5b88d5760320 2810 if( rs_ctx != NULL && rs_ctx->in_progress == x509_crt_rs_find_parent )
kenjiArai 0:5b88d5760320 2811 {
kenjiArai 0:5b88d5760320 2812 /* restore saved state */
kenjiArai 0:5b88d5760320 2813 *ver_chain = rs_ctx->ver_chain; /* struct copy */
kenjiArai 0:5b88d5760320 2814 self_cnt = rs_ctx->self_cnt;
kenjiArai 0:5b88d5760320 2815
kenjiArai 0:5b88d5760320 2816 /* restore derived state */
kenjiArai 0:5b88d5760320 2817 cur = &ver_chain->items[ver_chain->len - 1];
kenjiArai 0:5b88d5760320 2818 child = cur->crt;
kenjiArai 0:5b88d5760320 2819 flags = &cur->flags;
kenjiArai 0:5b88d5760320 2820
kenjiArai 0:5b88d5760320 2821 goto find_parent;
kenjiArai 0:5b88d5760320 2822 }
kenjiArai 0:5b88d5760320 2823 #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
kenjiArai 0:5b88d5760320 2824
kenjiArai 0:5b88d5760320 2825 child = crt;
kenjiArai 0:5b88d5760320 2826 self_cnt = 0;
kenjiArai 0:5b88d5760320 2827 parent_is_trusted = 0;
kenjiArai 0:5b88d5760320 2828 child_is_trusted = 0;
kenjiArai 0:5b88d5760320 2829
kenjiArai 0:5b88d5760320 2830 while( 1 ) {
kenjiArai 0:5b88d5760320 2831 /* Add certificate to the verification chain */
kenjiArai 0:5b88d5760320 2832 cur = &ver_chain->items[ver_chain->len];
kenjiArai 0:5b88d5760320 2833 cur->crt = child;
kenjiArai 0:5b88d5760320 2834 cur->flags = 0;
kenjiArai 0:5b88d5760320 2835 ver_chain->len++;
kenjiArai 0:5b88d5760320 2836 flags = &cur->flags;
kenjiArai 0:5b88d5760320 2837
kenjiArai 0:5b88d5760320 2838 /* Check time-validity (all certificates) */
kenjiArai 0:5b88d5760320 2839 if( mbedtls_x509_time_is_past( &child->valid_to ) )
kenjiArai 0:5b88d5760320 2840 *flags |= MBEDTLS_X509_BADCERT_EXPIRED;
kenjiArai 0:5b88d5760320 2841
kenjiArai 0:5b88d5760320 2842 if( mbedtls_x509_time_is_future( &child->valid_from ) )
kenjiArai 0:5b88d5760320 2843 *flags |= MBEDTLS_X509_BADCERT_FUTURE;
kenjiArai 0:5b88d5760320 2844
kenjiArai 0:5b88d5760320 2845 /* Stop here for trusted roots (but not for trusted EE certs) */
kenjiArai 0:5b88d5760320 2846 if( child_is_trusted )
kenjiArai 0:5b88d5760320 2847 return( 0 );
kenjiArai 0:5b88d5760320 2848
kenjiArai 0:5b88d5760320 2849 /* Check signature algorithm: MD & PK algs */
kenjiArai 0:5b88d5760320 2850 if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 )
kenjiArai 0:5b88d5760320 2851 *flags |= MBEDTLS_X509_BADCERT_BAD_MD;
kenjiArai 0:5b88d5760320 2852
kenjiArai 0:5b88d5760320 2853 if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 )
kenjiArai 0:5b88d5760320 2854 *flags |= MBEDTLS_X509_BADCERT_BAD_PK;
kenjiArai 0:5b88d5760320 2855
kenjiArai 0:5b88d5760320 2856 /* Special case: EE certs that are locally trusted */
kenjiArai 0:5b88d5760320 2857 if( ver_chain->len == 1 &&
kenjiArai 0:5b88d5760320 2858 x509_crt_check_ee_locally_trusted( child, trust_ca ) == 0 )
kenjiArai 0:5b88d5760320 2859 {
kenjiArai 0:5b88d5760320 2860 return( 0 );
kenjiArai 0:5b88d5760320 2861 }
kenjiArai 0:5b88d5760320 2862
kenjiArai 0:5b88d5760320 2863 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
kenjiArai 0:5b88d5760320 2864 find_parent:
kenjiArai 0:5b88d5760320 2865 #endif
kenjiArai 0:5b88d5760320 2866
kenjiArai 0:5b88d5760320 2867 /* Obtain list of potential trusted signers from CA callback,
kenjiArai 0:5b88d5760320 2868 * or use statically provided list. */
kenjiArai 0:5b88d5760320 2869 #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
kenjiArai 0:5b88d5760320 2870 if( f_ca_cb != NULL )
kenjiArai 0:5b88d5760320 2871 {
kenjiArai 0:5b88d5760320 2872 mbedtls_x509_crt_free( ver_chain->trust_ca_cb_result );
kenjiArai 0:5b88d5760320 2873 mbedtls_free( ver_chain->trust_ca_cb_result );
kenjiArai 0:5b88d5760320 2874 ver_chain->trust_ca_cb_result = NULL;
kenjiArai 0:5b88d5760320 2875
kenjiArai 0:5b88d5760320 2876 ret = f_ca_cb( p_ca_cb, child, &ver_chain->trust_ca_cb_result );
kenjiArai 0:5b88d5760320 2877 if( ret != 0 )
kenjiArai 0:5b88d5760320 2878 return( MBEDTLS_ERR_X509_FATAL_ERROR );
kenjiArai 0:5b88d5760320 2879
kenjiArai 0:5b88d5760320 2880 cur_trust_ca = ver_chain->trust_ca_cb_result;
kenjiArai 0:5b88d5760320 2881 }
kenjiArai 0:5b88d5760320 2882 else
kenjiArai 0:5b88d5760320 2883 #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
kenjiArai 0:5b88d5760320 2884 {
kenjiArai 0:5b88d5760320 2885 ((void) f_ca_cb);
kenjiArai 0:5b88d5760320 2886 ((void) p_ca_cb);
kenjiArai 0:5b88d5760320 2887 cur_trust_ca = trust_ca;
kenjiArai 0:5b88d5760320 2888 }
kenjiArai 0:5b88d5760320 2889
kenjiArai 0:5b88d5760320 2890 /* Look for a parent in trusted CAs or up the chain */
kenjiArai 0:5b88d5760320 2891 ret = x509_crt_find_parent( child, cur_trust_ca, &parent,
kenjiArai 0:5b88d5760320 2892 &parent_is_trusted, &signature_is_good,
kenjiArai 0:5b88d5760320 2893 ver_chain->len - 1, self_cnt, rs_ctx );
kenjiArai 0:5b88d5760320 2894
kenjiArai 0:5b88d5760320 2895 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
kenjiArai 0:5b88d5760320 2896 if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
kenjiArai 0:5b88d5760320 2897 {
kenjiArai 0:5b88d5760320 2898 /* save state */
kenjiArai 0:5b88d5760320 2899 rs_ctx->in_progress = x509_crt_rs_find_parent;
kenjiArai 0:5b88d5760320 2900 rs_ctx->self_cnt = self_cnt;
kenjiArai 0:5b88d5760320 2901 rs_ctx->ver_chain = *ver_chain; /* struct copy */
kenjiArai 0:5b88d5760320 2902
kenjiArai 0:5b88d5760320 2903 return( ret );
kenjiArai 0:5b88d5760320 2904 }
kenjiArai 0:5b88d5760320 2905 #else
kenjiArai 0:5b88d5760320 2906 (void) ret;
kenjiArai 0:5b88d5760320 2907 #endif
kenjiArai 0:5b88d5760320 2908
kenjiArai 0:5b88d5760320 2909 /* No parent? We're done here */
kenjiArai 0:5b88d5760320 2910 if( parent == NULL )
kenjiArai 0:5b88d5760320 2911 {
kenjiArai 0:5b88d5760320 2912 *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
kenjiArai 0:5b88d5760320 2913 return( 0 );
kenjiArai 0:5b88d5760320 2914 }
kenjiArai 0:5b88d5760320 2915
kenjiArai 0:5b88d5760320 2916 /* Count intermediate self-issued (not necessarily self-signed) certs.
kenjiArai 0:5b88d5760320 2917 * These can occur with some strategies for key rollover, see [SIRO],
kenjiArai 0:5b88d5760320 2918 * and should be excluded from max_pathlen checks. */
kenjiArai 0:5b88d5760320 2919 if( ver_chain->len != 1 &&
kenjiArai 0:5b88d5760320 2920 x509_name_cmp( &child->issuer, &child->subject ) == 0 )
kenjiArai 0:5b88d5760320 2921 {
kenjiArai 0:5b88d5760320 2922 self_cnt++;
kenjiArai 0:5b88d5760320 2923 }
kenjiArai 0:5b88d5760320 2924
kenjiArai 0:5b88d5760320 2925 /* path_cnt is 0 for the first intermediate CA,
kenjiArai 0:5b88d5760320 2926 * and if parent is trusted it's not an intermediate CA */
kenjiArai 0:5b88d5760320 2927 if( ! parent_is_trusted &&
kenjiArai 0:5b88d5760320 2928 ver_chain->len > MBEDTLS_X509_MAX_INTERMEDIATE_CA )
kenjiArai 0:5b88d5760320 2929 {
kenjiArai 0:5b88d5760320 2930 /* return immediately to avoid overflow the chain array */
kenjiArai 0:5b88d5760320 2931 return( MBEDTLS_ERR_X509_FATAL_ERROR );
kenjiArai 0:5b88d5760320 2932 }
kenjiArai 0:5b88d5760320 2933
kenjiArai 0:5b88d5760320 2934 /* signature was checked while searching parent */
kenjiArai 0:5b88d5760320 2935 if( ! signature_is_good )
kenjiArai 0:5b88d5760320 2936 *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
kenjiArai 0:5b88d5760320 2937
kenjiArai 0:5b88d5760320 2938 /* check size of signing key */
kenjiArai 0:5b88d5760320 2939 if( x509_profile_check_key( profile, &parent->pk ) != 0 )
kenjiArai 0:5b88d5760320 2940 *flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
kenjiArai 0:5b88d5760320 2941
kenjiArai 0:5b88d5760320 2942 #if defined(MBEDTLS_X509_CRL_PARSE_C)
kenjiArai 0:5b88d5760320 2943 /* Check trusted CA's CRL for the given crt */
kenjiArai 0:5b88d5760320 2944 *flags |= x509_crt_verifycrl( child, parent, ca_crl, profile );
kenjiArai 0:5b88d5760320 2945 #else
kenjiArai 0:5b88d5760320 2946 (void) ca_crl;
kenjiArai 0:5b88d5760320 2947 #endif
kenjiArai 0:5b88d5760320 2948
kenjiArai 0:5b88d5760320 2949 /* prepare for next iteration */
kenjiArai 0:5b88d5760320 2950 child = parent;
kenjiArai 0:5b88d5760320 2951 parent = NULL;
kenjiArai 0:5b88d5760320 2952 child_is_trusted = parent_is_trusted;
kenjiArai 0:5b88d5760320 2953 signature_is_good = 0;
kenjiArai 0:5b88d5760320 2954 }
kenjiArai 0:5b88d5760320 2955 }
kenjiArai 0:5b88d5760320 2956
kenjiArai 0:5b88d5760320 2957 /*
kenjiArai 0:5b88d5760320 2958 * Check for CN match
kenjiArai 0:5b88d5760320 2959 */
kenjiArai 0:5b88d5760320 2960 static int x509_crt_check_cn( const mbedtls_x509_buf *name,
kenjiArai 0:5b88d5760320 2961 const char *cn, size_t cn_len )
kenjiArai 0:5b88d5760320 2962 {
kenjiArai 0:5b88d5760320 2963 /* try exact match */
kenjiArai 0:5b88d5760320 2964 if( name->len == cn_len &&
kenjiArai 0:5b88d5760320 2965 x509_memcasecmp( cn, name->p, cn_len ) == 0 )
kenjiArai 0:5b88d5760320 2966 {
kenjiArai 0:5b88d5760320 2967 return( 0 );
kenjiArai 0:5b88d5760320 2968 }
kenjiArai 0:5b88d5760320 2969
kenjiArai 0:5b88d5760320 2970 /* try wildcard match */
kenjiArai 0:5b88d5760320 2971 if( x509_check_wildcard( cn, name ) == 0 )
kenjiArai 0:5b88d5760320 2972 {
kenjiArai 0:5b88d5760320 2973 return( 0 );
kenjiArai 0:5b88d5760320 2974 }
kenjiArai 0:5b88d5760320 2975
kenjiArai 0:5b88d5760320 2976 return( -1 );
kenjiArai 0:5b88d5760320 2977 }
kenjiArai 0:5b88d5760320 2978
kenjiArai 0:5b88d5760320 2979 /*
kenjiArai 0:5b88d5760320 2980 * Verify the requested CN - only call this if cn is not NULL!
kenjiArai 0:5b88d5760320 2981 */
kenjiArai 0:5b88d5760320 2982 static void x509_crt_verify_name( const mbedtls_x509_crt *crt,
kenjiArai 0:5b88d5760320 2983 const char *cn,
kenjiArai 0:5b88d5760320 2984 uint32_t *flags )
kenjiArai 0:5b88d5760320 2985 {
kenjiArai 0:5b88d5760320 2986 const mbedtls_x509_name *name;
kenjiArai 0:5b88d5760320 2987 const mbedtls_x509_sequence *cur;
kenjiArai 0:5b88d5760320 2988 size_t cn_len = strlen( cn );
kenjiArai 0:5b88d5760320 2989
kenjiArai 0:5b88d5760320 2990 if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
kenjiArai 0:5b88d5760320 2991 {
kenjiArai 0:5b88d5760320 2992 for( cur = &crt->subject_alt_names; cur != NULL; cur = cur->next )
kenjiArai 0:5b88d5760320 2993 {
kenjiArai 0:5b88d5760320 2994 if( x509_crt_check_cn( &cur->buf, cn, cn_len ) == 0 )
kenjiArai 0:5b88d5760320 2995 break;
kenjiArai 0:5b88d5760320 2996 }
kenjiArai 0:5b88d5760320 2997
kenjiArai 0:5b88d5760320 2998 if( cur == NULL )
kenjiArai 0:5b88d5760320 2999 *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
kenjiArai 0:5b88d5760320 3000 }
kenjiArai 0:5b88d5760320 3001 else
kenjiArai 0:5b88d5760320 3002 {
kenjiArai 0:5b88d5760320 3003 for( name = &crt->subject; name != NULL; name = name->next )
kenjiArai 0:5b88d5760320 3004 {
kenjiArai 0:5b88d5760320 3005 if( MBEDTLS_OID_CMP( MBEDTLS_OID_AT_CN, &name->oid ) == 0 &&
kenjiArai 0:5b88d5760320 3006 x509_crt_check_cn( &name->val, cn, cn_len ) == 0 )
kenjiArai 0:5b88d5760320 3007 {
kenjiArai 0:5b88d5760320 3008 break;
kenjiArai 0:5b88d5760320 3009 }
kenjiArai 0:5b88d5760320 3010 }
kenjiArai 0:5b88d5760320 3011
kenjiArai 0:5b88d5760320 3012 if( name == NULL )
kenjiArai 0:5b88d5760320 3013 *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
kenjiArai 0:5b88d5760320 3014 }
kenjiArai 0:5b88d5760320 3015 }
kenjiArai 0:5b88d5760320 3016
kenjiArai 0:5b88d5760320 3017 /*
kenjiArai 0:5b88d5760320 3018 * Merge the flags for all certs in the chain, after calling callback
kenjiArai 0:5b88d5760320 3019 */
kenjiArai 0:5b88d5760320 3020 static int x509_crt_merge_flags_with_cb(
kenjiArai 0:5b88d5760320 3021 uint32_t *flags,
kenjiArai 0:5b88d5760320 3022 const mbedtls_x509_crt_verify_chain *ver_chain,
kenjiArai 0:5b88d5760320 3023 int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
kenjiArai 0:5b88d5760320 3024 void *p_vrfy )
kenjiArai 0:5b88d5760320 3025 {
kenjiArai 0:5b88d5760320 3026 int ret;
kenjiArai 0:5b88d5760320 3027 unsigned i;
kenjiArai 0:5b88d5760320 3028 uint32_t cur_flags;
kenjiArai 0:5b88d5760320 3029 const mbedtls_x509_crt_verify_chain_item *cur;
kenjiArai 0:5b88d5760320 3030
kenjiArai 0:5b88d5760320 3031 for( i = ver_chain->len; i != 0; --i )
kenjiArai 0:5b88d5760320 3032 {
kenjiArai 0:5b88d5760320 3033 cur = &ver_chain->items[i-1];
kenjiArai 0:5b88d5760320 3034 cur_flags = cur->flags;
kenjiArai 0:5b88d5760320 3035
kenjiArai 0:5b88d5760320 3036 if( NULL != f_vrfy )
kenjiArai 0:5b88d5760320 3037 if( ( ret = f_vrfy( p_vrfy, cur->crt, (int) i-1, &cur_flags ) ) != 0 )
kenjiArai 0:5b88d5760320 3038 return( ret );
kenjiArai 0:5b88d5760320 3039
kenjiArai 0:5b88d5760320 3040 *flags |= cur_flags;
kenjiArai 0:5b88d5760320 3041 }
kenjiArai 0:5b88d5760320 3042
kenjiArai 0:5b88d5760320 3043 return( 0 );
kenjiArai 0:5b88d5760320 3044 }
kenjiArai 0:5b88d5760320 3045
kenjiArai 0:5b88d5760320 3046 /*
kenjiArai 0:5b88d5760320 3047 * Verify the certificate validity, with profile, restartable version
kenjiArai 0:5b88d5760320 3048 *
kenjiArai 0:5b88d5760320 3049 * This function:
kenjiArai 0:5b88d5760320 3050 * - checks the requested CN (if any)
kenjiArai 0:5b88d5760320 3051 * - checks the type and size of the EE cert's key,
kenjiArai 0:5b88d5760320 3052 * as that isn't done as part of chain building/verification currently
kenjiArai 0:5b88d5760320 3053 * - builds and verifies the chain
kenjiArai 0:5b88d5760320 3054 * - then calls the callback and merges the flags
kenjiArai 0:5b88d5760320 3055 *
kenjiArai 0:5b88d5760320 3056 * The parameters pairs `trust_ca`, `ca_crl` and `f_ca_cb`, `p_ca_cb`
kenjiArai 0:5b88d5760320 3057 * are mutually exclusive: If `f_ca_cb != NULL`, it will be used by the
kenjiArai 0:5b88d5760320 3058 * verification routine to search for trusted signers, and CRLs will
kenjiArai 0:5b88d5760320 3059 * be disabled. Otherwise, `trust_ca` will be used as the static list
kenjiArai 0:5b88d5760320 3060 * of trusted signers, and `ca_crl` will be use as the static list
kenjiArai 0:5b88d5760320 3061 * of CRLs.
kenjiArai 0:5b88d5760320 3062 */
kenjiArai 0:5b88d5760320 3063 static int x509_crt_verify_restartable_ca_cb( mbedtls_x509_crt *crt,
kenjiArai 0:5b88d5760320 3064 mbedtls_x509_crt *trust_ca,
kenjiArai 0:5b88d5760320 3065 mbedtls_x509_crl *ca_crl,
kenjiArai 0:5b88d5760320 3066 mbedtls_x509_crt_ca_cb_t f_ca_cb,
kenjiArai 0:5b88d5760320 3067 void *p_ca_cb,
kenjiArai 0:5b88d5760320 3068 const mbedtls_x509_crt_profile *profile,
kenjiArai 0:5b88d5760320 3069 const char *cn, uint32_t *flags,
kenjiArai 0:5b88d5760320 3070 int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
kenjiArai 0:5b88d5760320 3071 void *p_vrfy,
kenjiArai 0:5b88d5760320 3072 mbedtls_x509_crt_restart_ctx *rs_ctx )
kenjiArai 0:5b88d5760320 3073 {
kenjiArai 0:5b88d5760320 3074 int ret;
kenjiArai 0:5b88d5760320 3075 mbedtls_pk_type_t pk_type;
kenjiArai 0:5b88d5760320 3076 mbedtls_x509_crt_verify_chain ver_chain;
kenjiArai 0:5b88d5760320 3077 uint32_t ee_flags;
kenjiArai 0:5b88d5760320 3078
kenjiArai 0:5b88d5760320 3079 *flags = 0;
kenjiArai 0:5b88d5760320 3080 ee_flags = 0;
kenjiArai 0:5b88d5760320 3081 x509_crt_verify_chain_reset( &ver_chain );
kenjiArai 0:5b88d5760320 3082
kenjiArai 0:5b88d5760320 3083 if( profile == NULL )
kenjiArai 0:5b88d5760320 3084 {
kenjiArai 0:5b88d5760320 3085 ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA;
kenjiArai 0:5b88d5760320 3086 goto exit;
kenjiArai 0:5b88d5760320 3087 }
kenjiArai 0:5b88d5760320 3088
kenjiArai 0:5b88d5760320 3089 /* check name if requested */
kenjiArai 0:5b88d5760320 3090 if( cn != NULL )
kenjiArai 0:5b88d5760320 3091 x509_crt_verify_name( crt, cn, &ee_flags );
kenjiArai 0:5b88d5760320 3092
kenjiArai 0:5b88d5760320 3093 /* Check the type and size of the key */
kenjiArai 0:5b88d5760320 3094 pk_type = mbedtls_pk_get_type( &crt->pk );
kenjiArai 0:5b88d5760320 3095
kenjiArai 0:5b88d5760320 3096 if( x509_profile_check_pk_alg( profile, pk_type ) != 0 )
kenjiArai 0:5b88d5760320 3097 ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK;
kenjiArai 0:5b88d5760320 3098
kenjiArai 0:5b88d5760320 3099 if( x509_profile_check_key( profile, &crt->pk ) != 0 )
kenjiArai 0:5b88d5760320 3100 ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
kenjiArai 0:5b88d5760320 3101
kenjiArai 0:5b88d5760320 3102 /* Check the chain */
kenjiArai 0:5b88d5760320 3103 ret = x509_crt_verify_chain( crt, trust_ca, ca_crl,
kenjiArai 0:5b88d5760320 3104 f_ca_cb, p_ca_cb, profile,
kenjiArai 0:5b88d5760320 3105 &ver_chain, rs_ctx );
kenjiArai 0:5b88d5760320 3106
kenjiArai 0:5b88d5760320 3107 if( ret != 0 )
kenjiArai 0:5b88d5760320 3108 goto exit;
kenjiArai 0:5b88d5760320 3109
kenjiArai 0:5b88d5760320 3110 /* Merge end-entity flags */
kenjiArai 0:5b88d5760320 3111 ver_chain.items[0].flags |= ee_flags;
kenjiArai 0:5b88d5760320 3112
kenjiArai 0:5b88d5760320 3113 /* Build final flags, calling callback on the way if any */
kenjiArai 0:5b88d5760320 3114 ret = x509_crt_merge_flags_with_cb( flags, &ver_chain, f_vrfy, p_vrfy );
kenjiArai 0:5b88d5760320 3115
kenjiArai 0:5b88d5760320 3116 exit:
kenjiArai 0:5b88d5760320 3117
kenjiArai 0:5b88d5760320 3118 #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
kenjiArai 0:5b88d5760320 3119 mbedtls_x509_crt_free( ver_chain.trust_ca_cb_result );
kenjiArai 0:5b88d5760320 3120 mbedtls_free( ver_chain.trust_ca_cb_result );
kenjiArai 0:5b88d5760320 3121 ver_chain.trust_ca_cb_result = NULL;
kenjiArai 0:5b88d5760320 3122 #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
kenjiArai 0:5b88d5760320 3123
kenjiArai 0:5b88d5760320 3124 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
kenjiArai 0:5b88d5760320 3125 if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
kenjiArai 0:5b88d5760320 3126 mbedtls_x509_crt_restart_free( rs_ctx );
kenjiArai 0:5b88d5760320 3127 #endif
kenjiArai 0:5b88d5760320 3128
kenjiArai 0:5b88d5760320 3129 /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by
kenjiArai 0:5b88d5760320 3130 * the SSL module for authmode optional, but non-zero return from the
kenjiArai 0:5b88d5760320 3131 * callback means a fatal error so it shouldn't be ignored */
kenjiArai 0:5b88d5760320 3132 if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED )
kenjiArai 0:5b88d5760320 3133 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
kenjiArai 0:5b88d5760320 3134
kenjiArai 0:5b88d5760320 3135 if( ret != 0 )
kenjiArai 0:5b88d5760320 3136 {
kenjiArai 0:5b88d5760320 3137 *flags = (uint32_t) -1;
kenjiArai 0:5b88d5760320 3138 return( ret );
kenjiArai 0:5b88d5760320 3139 }
kenjiArai 0:5b88d5760320 3140
kenjiArai 0:5b88d5760320 3141 if( *flags != 0 )
kenjiArai 0:5b88d5760320 3142 return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED );
kenjiArai 0:5b88d5760320 3143
kenjiArai 0:5b88d5760320 3144 return( 0 );
kenjiArai 0:5b88d5760320 3145 }
kenjiArai 0:5b88d5760320 3146
kenjiArai 0:5b88d5760320 3147
kenjiArai 0:5b88d5760320 3148 /*
kenjiArai 0:5b88d5760320 3149 * Verify the certificate validity (default profile, not restartable)
kenjiArai 0:5b88d5760320 3150 */
kenjiArai 0:5b88d5760320 3151 int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt,
kenjiArai 0:5b88d5760320 3152 mbedtls_x509_crt *trust_ca,
kenjiArai 0:5b88d5760320 3153 mbedtls_x509_crl *ca_crl,
kenjiArai 0:5b88d5760320 3154 const char *cn, uint32_t *flags,
kenjiArai 0:5b88d5760320 3155 int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
kenjiArai 0:5b88d5760320 3156 void *p_vrfy )
kenjiArai 0:5b88d5760320 3157 {
kenjiArai 0:5b88d5760320 3158 return( x509_crt_verify_restartable_ca_cb( crt, trust_ca, ca_crl,
kenjiArai 0:5b88d5760320 3159 NULL, NULL,
kenjiArai 0:5b88d5760320 3160 &mbedtls_x509_crt_profile_default,
kenjiArai 0:5b88d5760320 3161 cn, flags,
kenjiArai 0:5b88d5760320 3162 f_vrfy, p_vrfy, NULL ) );
kenjiArai 0:5b88d5760320 3163 }
kenjiArai 0:5b88d5760320 3164
kenjiArai 0:5b88d5760320 3165 /*
kenjiArai 0:5b88d5760320 3166 * Verify the certificate validity (user-chosen profile, not restartable)
kenjiArai 0:5b88d5760320 3167 */
kenjiArai 0:5b88d5760320 3168 int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
kenjiArai 0:5b88d5760320 3169 mbedtls_x509_crt *trust_ca,
kenjiArai 0:5b88d5760320 3170 mbedtls_x509_crl *ca_crl,
kenjiArai 0:5b88d5760320 3171 const mbedtls_x509_crt_profile *profile,
kenjiArai 0:5b88d5760320 3172 const char *cn, uint32_t *flags,
kenjiArai 0:5b88d5760320 3173 int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
kenjiArai 0:5b88d5760320 3174 void *p_vrfy )
kenjiArai 0:5b88d5760320 3175 {
kenjiArai 0:5b88d5760320 3176 return( x509_crt_verify_restartable_ca_cb( crt, trust_ca, ca_crl,
kenjiArai 0:5b88d5760320 3177 NULL, NULL,
kenjiArai 0:5b88d5760320 3178 profile, cn, flags,
kenjiArai 0:5b88d5760320 3179 f_vrfy, p_vrfy, NULL ) );
kenjiArai 0:5b88d5760320 3180 }
kenjiArai 0:5b88d5760320 3181
kenjiArai 0:5b88d5760320 3182 #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
kenjiArai 0:5b88d5760320 3183 /*
kenjiArai 0:5b88d5760320 3184 * Verify the certificate validity (user-chosen profile, CA callback,
kenjiArai 0:5b88d5760320 3185 * not restartable).
kenjiArai 0:5b88d5760320 3186 */
kenjiArai 0:5b88d5760320 3187 int mbedtls_x509_crt_verify_with_ca_cb( mbedtls_x509_crt *crt,
kenjiArai 0:5b88d5760320 3188 mbedtls_x509_crt_ca_cb_t f_ca_cb,
kenjiArai 0:5b88d5760320 3189 void *p_ca_cb,
kenjiArai 0:5b88d5760320 3190 const mbedtls_x509_crt_profile *profile,
kenjiArai 0:5b88d5760320 3191 const char *cn, uint32_t *flags,
kenjiArai 0:5b88d5760320 3192 int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
kenjiArai 0:5b88d5760320 3193 void *p_vrfy )
kenjiArai 0:5b88d5760320 3194 {
kenjiArai 0:5b88d5760320 3195 return( x509_crt_verify_restartable_ca_cb( crt, NULL, NULL,
kenjiArai 0:5b88d5760320 3196 f_ca_cb, p_ca_cb,
kenjiArai 0:5b88d5760320 3197 profile, cn, flags,
kenjiArai 0:5b88d5760320 3198 f_vrfy, p_vrfy, NULL ) );
kenjiArai 0:5b88d5760320 3199 }
kenjiArai 0:5b88d5760320 3200 #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
kenjiArai 0:5b88d5760320 3201
kenjiArai 0:5b88d5760320 3202 int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt,
kenjiArai 0:5b88d5760320 3203 mbedtls_x509_crt *trust_ca,
kenjiArai 0:5b88d5760320 3204 mbedtls_x509_crl *ca_crl,
kenjiArai 0:5b88d5760320 3205 const mbedtls_x509_crt_profile *profile,
kenjiArai 0:5b88d5760320 3206 const char *cn, uint32_t *flags,
kenjiArai 0:5b88d5760320 3207 int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
kenjiArai 0:5b88d5760320 3208 void *p_vrfy,
kenjiArai 0:5b88d5760320 3209 mbedtls_x509_crt_restart_ctx *rs_ctx )
kenjiArai 0:5b88d5760320 3210 {
kenjiArai 0:5b88d5760320 3211 return( x509_crt_verify_restartable_ca_cb( crt, trust_ca, ca_crl,
kenjiArai 0:5b88d5760320 3212 NULL, NULL,
kenjiArai 0:5b88d5760320 3213 profile, cn, flags,
kenjiArai 0:5b88d5760320 3214 f_vrfy, p_vrfy, rs_ctx ) );
kenjiArai 0:5b88d5760320 3215 }
kenjiArai 0:5b88d5760320 3216
kenjiArai 0:5b88d5760320 3217
kenjiArai 0:5b88d5760320 3218 /*
kenjiArai 0:5b88d5760320 3219 * Initialize a certificate chain
kenjiArai 0:5b88d5760320 3220 */
kenjiArai 0:5b88d5760320 3221 void mbedtls_x509_crt_init( mbedtls_x509_crt *crt )
kenjiArai 0:5b88d5760320 3222 {
kenjiArai 0:5b88d5760320 3223 memset( crt, 0, sizeof(mbedtls_x509_crt) );
kenjiArai 0:5b88d5760320 3224 }
kenjiArai 0:5b88d5760320 3225
kenjiArai 0:5b88d5760320 3226 /*
kenjiArai 0:5b88d5760320 3227 * Unallocate all certificate data
kenjiArai 0:5b88d5760320 3228 */
kenjiArai 0:5b88d5760320 3229 void mbedtls_x509_crt_free( mbedtls_x509_crt *crt )
kenjiArai 0:5b88d5760320 3230 {
kenjiArai 0:5b88d5760320 3231 mbedtls_x509_crt *cert_cur = crt;
kenjiArai 0:5b88d5760320 3232 mbedtls_x509_crt *cert_prv;
kenjiArai 0:5b88d5760320 3233 mbedtls_x509_name *name_cur;
kenjiArai 0:5b88d5760320 3234 mbedtls_x509_name *name_prv;
kenjiArai 0:5b88d5760320 3235 mbedtls_x509_sequence *seq_cur;
kenjiArai 0:5b88d5760320 3236 mbedtls_x509_sequence *seq_prv;
kenjiArai 0:5b88d5760320 3237
kenjiArai 0:5b88d5760320 3238 if( crt == NULL )
kenjiArai 0:5b88d5760320 3239 return;
kenjiArai 0:5b88d5760320 3240
kenjiArai 0:5b88d5760320 3241 do
kenjiArai 0:5b88d5760320 3242 {
kenjiArai 0:5b88d5760320 3243 mbedtls_pk_free( &cert_cur->pk );
kenjiArai 0:5b88d5760320 3244
kenjiArai 0:5b88d5760320 3245 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
kenjiArai 0:5b88d5760320 3246 mbedtls_free( cert_cur->sig_opts );
kenjiArai 0:5b88d5760320 3247 #endif
kenjiArai 0:5b88d5760320 3248
kenjiArai 0:5b88d5760320 3249 name_cur = cert_cur->issuer.next;
kenjiArai 0:5b88d5760320 3250 while( name_cur != NULL )
kenjiArai 0:5b88d5760320 3251 {
kenjiArai 0:5b88d5760320 3252 name_prv = name_cur;
kenjiArai 0:5b88d5760320 3253 name_cur = name_cur->next;
kenjiArai 0:5b88d5760320 3254 mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) );
kenjiArai 0:5b88d5760320 3255 mbedtls_free( name_prv );
kenjiArai 0:5b88d5760320 3256 }
kenjiArai 0:5b88d5760320 3257
kenjiArai 0:5b88d5760320 3258 name_cur = cert_cur->subject.next;
kenjiArai 0:5b88d5760320 3259 while( name_cur != NULL )
kenjiArai 0:5b88d5760320 3260 {
kenjiArai 0:5b88d5760320 3261 name_prv = name_cur;
kenjiArai 0:5b88d5760320 3262 name_cur = name_cur->next;
kenjiArai 0:5b88d5760320 3263 mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) );
kenjiArai 0:5b88d5760320 3264 mbedtls_free( name_prv );
kenjiArai 0:5b88d5760320 3265 }
kenjiArai 0:5b88d5760320 3266
kenjiArai 0:5b88d5760320 3267 seq_cur = cert_cur->ext_key_usage.next;
kenjiArai 0:5b88d5760320 3268 while( seq_cur != NULL )
kenjiArai 0:5b88d5760320 3269 {
kenjiArai 0:5b88d5760320 3270 seq_prv = seq_cur;
kenjiArai 0:5b88d5760320 3271 seq_cur = seq_cur->next;
kenjiArai 0:5b88d5760320 3272 mbedtls_platform_zeroize( seq_prv,
kenjiArai 0:5b88d5760320 3273 sizeof( mbedtls_x509_sequence ) );
kenjiArai 0:5b88d5760320 3274 mbedtls_free( seq_prv );
kenjiArai 0:5b88d5760320 3275 }
kenjiArai 0:5b88d5760320 3276
kenjiArai 0:5b88d5760320 3277 seq_cur = cert_cur->subject_alt_names.next;
kenjiArai 0:5b88d5760320 3278 while( seq_cur != NULL )
kenjiArai 0:5b88d5760320 3279 {
kenjiArai 0:5b88d5760320 3280 seq_prv = seq_cur;
kenjiArai 0:5b88d5760320 3281 seq_cur = seq_cur->next;
kenjiArai 0:5b88d5760320 3282 mbedtls_platform_zeroize( seq_prv,
kenjiArai 0:5b88d5760320 3283 sizeof( mbedtls_x509_sequence ) );
kenjiArai 0:5b88d5760320 3284 mbedtls_free( seq_prv );
kenjiArai 0:5b88d5760320 3285 }
kenjiArai 0:5b88d5760320 3286
kenjiArai 0:5b88d5760320 3287 seq_cur = cert_cur->certificate_policies.next;
kenjiArai 0:5b88d5760320 3288 while( seq_cur != NULL )
kenjiArai 0:5b88d5760320 3289 {
kenjiArai 0:5b88d5760320 3290 seq_prv = seq_cur;
kenjiArai 0:5b88d5760320 3291 seq_cur = seq_cur->next;
kenjiArai 0:5b88d5760320 3292 mbedtls_platform_zeroize( seq_prv,
kenjiArai 0:5b88d5760320 3293 sizeof( mbedtls_x509_sequence ) );
kenjiArai 0:5b88d5760320 3294 mbedtls_free( seq_prv );
kenjiArai 0:5b88d5760320 3295 }
kenjiArai 0:5b88d5760320 3296
kenjiArai 0:5b88d5760320 3297 if( cert_cur->raw.p != NULL && cert_cur->own_buffer )
kenjiArai 0:5b88d5760320 3298 {
kenjiArai 0:5b88d5760320 3299 mbedtls_platform_zeroize( cert_cur->raw.p, cert_cur->raw.len );
kenjiArai 0:5b88d5760320 3300 mbedtls_free( cert_cur->raw.p );
kenjiArai 0:5b88d5760320 3301 }
kenjiArai 0:5b88d5760320 3302
kenjiArai 0:5b88d5760320 3303 cert_cur = cert_cur->next;
kenjiArai 0:5b88d5760320 3304 }
kenjiArai 0:5b88d5760320 3305 while( cert_cur != NULL );
kenjiArai 0:5b88d5760320 3306
kenjiArai 0:5b88d5760320 3307 cert_cur = crt;
kenjiArai 0:5b88d5760320 3308 do
kenjiArai 0:5b88d5760320 3309 {
kenjiArai 0:5b88d5760320 3310 cert_prv = cert_cur;
kenjiArai 0:5b88d5760320 3311 cert_cur = cert_cur->next;
kenjiArai 0:5b88d5760320 3312
kenjiArai 0:5b88d5760320 3313 mbedtls_platform_zeroize( cert_prv, sizeof( mbedtls_x509_crt ) );
kenjiArai 0:5b88d5760320 3314 if( cert_prv != crt )
kenjiArai 0:5b88d5760320 3315 mbedtls_free( cert_prv );
kenjiArai 0:5b88d5760320 3316 }
kenjiArai 0:5b88d5760320 3317 while( cert_cur != NULL );
kenjiArai 0:5b88d5760320 3318 }
kenjiArai 0:5b88d5760320 3319
kenjiArai 0:5b88d5760320 3320 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
kenjiArai 0:5b88d5760320 3321 /*
kenjiArai 0:5b88d5760320 3322 * Initialize a restart context
kenjiArai 0:5b88d5760320 3323 */
kenjiArai 0:5b88d5760320 3324 void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx )
kenjiArai 0:5b88d5760320 3325 {
kenjiArai 0:5b88d5760320 3326 mbedtls_pk_restart_init( &ctx->pk );
kenjiArai 0:5b88d5760320 3327
kenjiArai 0:5b88d5760320 3328 ctx->parent = NULL;
kenjiArai 0:5b88d5760320 3329 ctx->fallback_parent = NULL;
kenjiArai 0:5b88d5760320 3330 ctx->fallback_signature_is_good = 0;
kenjiArai 0:5b88d5760320 3331
kenjiArai 0:5b88d5760320 3332 ctx->parent_is_trusted = -1;
kenjiArai 0:5b88d5760320 3333
kenjiArai 0:5b88d5760320 3334 ctx->in_progress = x509_crt_rs_none;
kenjiArai 0:5b88d5760320 3335 ctx->self_cnt = 0;
kenjiArai 0:5b88d5760320 3336 x509_crt_verify_chain_reset( &ctx->ver_chain );
kenjiArai 0:5b88d5760320 3337 }
kenjiArai 0:5b88d5760320 3338
kenjiArai 0:5b88d5760320 3339 /*
kenjiArai 0:5b88d5760320 3340 * Free the components of a restart context
kenjiArai 0:5b88d5760320 3341 */
kenjiArai 0:5b88d5760320 3342 void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx )
kenjiArai 0:5b88d5760320 3343 {
kenjiArai 0:5b88d5760320 3344 if( ctx == NULL )
kenjiArai 0:5b88d5760320 3345 return;
kenjiArai 0:5b88d5760320 3346
kenjiArai 0:5b88d5760320 3347 mbedtls_pk_restart_free( &ctx->pk );
kenjiArai 0:5b88d5760320 3348 mbedtls_x509_crt_restart_init( ctx );
kenjiArai 0:5b88d5760320 3349 }
kenjiArai 0:5b88d5760320 3350 #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
kenjiArai 0:5b88d5760320 3351
kenjiArai 0:5b88d5760320 3352 #endif /* MBEDTLS_X509_CRT_PARSE_C */