BA / SerialCom

Fork of OmniWheels by Gustav Atmel

Committer:
gustavatmel
Date:
Tue May 01 15:47:08 2018 +0000
Revision:
1:9c5af431a1f1
sdf

Who changed what in which revision?

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