Knight KE / Mbed OS Game_Master
Committer:
WFKnight
Date:
Thu Jun 21 13:51:43 2018 +0000
Revision:
0:9b3d4731edbb
UART, RTOS, LED

Who changed what in which revision?

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