mbed TLS library

Dependents:   HTTPClient-SSL WS_SERVER

Committer:
ansond
Date:
Thu Jun 11 03:27:03 2015 +0000
Revision:
0:137634ff4186
initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ansond 0:137634ff4186 1 /*
ansond 0:137634ff4186 2 * X.509 certificate parsing and verification
ansond 0:137634ff4186 3 *
ansond 0:137634ff4186 4 * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
ansond 0:137634ff4186 5 *
ansond 0:137634ff4186 6 * This file is part of mbed TLS (https://tls.mbed.org)
ansond 0:137634ff4186 7 *
ansond 0:137634ff4186 8 * This program is free software; you can redistribute it and/or modify
ansond 0:137634ff4186 9 * it under the terms of the GNU General Public License as published by
ansond 0:137634ff4186 10 * the Free Software Foundation; either version 2 of the License, or
ansond 0:137634ff4186 11 * (at your option) any later version.
ansond 0:137634ff4186 12 *
ansond 0:137634ff4186 13 * This program is distributed in the hope that it will be useful,
ansond 0:137634ff4186 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ansond 0:137634ff4186 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
ansond 0:137634ff4186 16 * GNU General Public License for more details.
ansond 0:137634ff4186 17 *
ansond 0:137634ff4186 18 * You should have received a copy of the GNU General Public License along
ansond 0:137634ff4186 19 * with this program; if not, write to the Free Software Foundation, Inc.,
ansond 0:137634ff4186 20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
ansond 0:137634ff4186 21 */
ansond 0:137634ff4186 22 /*
ansond 0:137634ff4186 23 * The ITU-T X.509 standard defines a certificate format for PKI.
ansond 0:137634ff4186 24 *
ansond 0:137634ff4186 25 * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)
ansond 0:137634ff4186 26 * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
ansond 0:137634ff4186 27 * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
ansond 0:137634ff4186 28 *
ansond 0:137634ff4186 29 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
ansond 0:137634ff4186 30 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
ansond 0:137634ff4186 31 */
ansond 0:137634ff4186 32
ansond 0:137634ff4186 33 #if !defined(POLARSSL_CONFIG_FILE)
ansond 0:137634ff4186 34 #include "polarssl/config.h"
ansond 0:137634ff4186 35 #else
ansond 0:137634ff4186 36 #include POLARSSL_CONFIG_FILE
ansond 0:137634ff4186 37 #endif
ansond 0:137634ff4186 38
ansond 0:137634ff4186 39 #if defined(POLARSSL_X509_CRT_PARSE_C)
ansond 0:137634ff4186 40
ansond 0:137634ff4186 41 #include "polarssl/x509_crt.h"
ansond 0:137634ff4186 42 #include "polarssl/oid.h"
ansond 0:137634ff4186 43
ansond 0:137634ff4186 44 #include <stdio.h>
ansond 0:137634ff4186 45 #include <string.h>
ansond 0:137634ff4186 46
ansond 0:137634ff4186 47 #if defined(POLARSSL_PEM_PARSE_C)
ansond 0:137634ff4186 48 #include "polarssl/pem.h"
ansond 0:137634ff4186 49 #endif
ansond 0:137634ff4186 50
ansond 0:137634ff4186 51 #if defined(POLARSSL_PLATFORM_C)
ansond 0:137634ff4186 52 #include "polarssl/platform.h"
ansond 0:137634ff4186 53 #else
ansond 0:137634ff4186 54 #include <stdlib.h>
ansond 0:137634ff4186 55 #define polarssl_free free
ansond 0:137634ff4186 56 #define polarssl_malloc malloc
ansond 0:137634ff4186 57 #define polarssl_snprintf snprintf
ansond 0:137634ff4186 58 #endif
ansond 0:137634ff4186 59
ansond 0:137634ff4186 60 #if defined(POLARSSL_THREADING_C)
ansond 0:137634ff4186 61 #include "polarssl/threading.h"
ansond 0:137634ff4186 62 #endif
ansond 0:137634ff4186 63
ansond 0:137634ff4186 64 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
ansond 0:137634ff4186 65 #include <windows.h>
ansond 0:137634ff4186 66 #else
ansond 0:137634ff4186 67 #include <time.h>
ansond 0:137634ff4186 68 #endif
ansond 0:137634ff4186 69
ansond 0:137634ff4186 70 #if defined(POLARSSL_FS_IO)
ansond 0:137634ff4186 71 #include <stdio.h>
ansond 0:137634ff4186 72 #if !defined(_WIN32) || defined(EFIX64) || defined(EFI32)
ansond 0:137634ff4186 73 #include <sys/types.h>
ansond 0:137634ff4186 74 #include <sys/stat.h>
ansond 0:137634ff4186 75 #include <dirent.h>
ansond 0:137634ff4186 76 #endif /* !_WIN32 || EFIX64 || EFI32 */
ansond 0:137634ff4186 77 #endif
ansond 0:137634ff4186 78
ansond 0:137634ff4186 79 /* Implementation that should never be optimized out by the compiler */
ansond 0:137634ff4186 80 static void polarssl_zeroize( void *v, size_t n ) {
ansond 0:137634ff4186 81 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
ansond 0:137634ff4186 82 }
ansond 0:137634ff4186 83
ansond 0:137634ff4186 84 /*
ansond 0:137634ff4186 85 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
ansond 0:137634ff4186 86 */
ansond 0:137634ff4186 87 static int x509_get_version( unsigned char **p,
ansond 0:137634ff4186 88 const unsigned char *end,
ansond 0:137634ff4186 89 int *ver )
ansond 0:137634ff4186 90 {
ansond 0:137634ff4186 91 int ret;
ansond 0:137634ff4186 92 size_t len;
ansond 0:137634ff4186 93
ansond 0:137634ff4186 94 if( ( ret = asn1_get_tag( p, end, &len,
ansond 0:137634ff4186 95 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) != 0 )
ansond 0:137634ff4186 96 {
ansond 0:137634ff4186 97 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
ansond 0:137634ff4186 98 {
ansond 0:137634ff4186 99 *ver = 0;
ansond 0:137634ff4186 100 return( 0 );
ansond 0:137634ff4186 101 }
ansond 0:137634ff4186 102
ansond 0:137634ff4186 103 return( ret );
ansond 0:137634ff4186 104 }
ansond 0:137634ff4186 105
ansond 0:137634ff4186 106 end = *p + len;
ansond 0:137634ff4186 107
ansond 0:137634ff4186 108 if( ( ret = asn1_get_int( p, end, ver ) ) != 0 )
ansond 0:137634ff4186 109 return( POLARSSL_ERR_X509_INVALID_VERSION + ret );
ansond 0:137634ff4186 110
ansond 0:137634ff4186 111 if( *p != end )
ansond 0:137634ff4186 112 return( POLARSSL_ERR_X509_INVALID_VERSION +
ansond 0:137634ff4186 113 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
ansond 0:137634ff4186 114
ansond 0:137634ff4186 115 return( 0 );
ansond 0:137634ff4186 116 }
ansond 0:137634ff4186 117
ansond 0:137634ff4186 118 /*
ansond 0:137634ff4186 119 * Validity ::= SEQUENCE {
ansond 0:137634ff4186 120 * notBefore Time,
ansond 0:137634ff4186 121 * notAfter Time }
ansond 0:137634ff4186 122 */
ansond 0:137634ff4186 123 static int x509_get_dates( unsigned char **p,
ansond 0:137634ff4186 124 const unsigned char *end,
ansond 0:137634ff4186 125 x509_time *from,
ansond 0:137634ff4186 126 x509_time *to )
ansond 0:137634ff4186 127 {
ansond 0:137634ff4186 128 int ret;
ansond 0:137634ff4186 129 size_t len;
ansond 0:137634ff4186 130
ansond 0:137634ff4186 131 if( ( ret = asn1_get_tag( p, end, &len,
ansond 0:137634ff4186 132 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
ansond 0:137634ff4186 133 return( POLARSSL_ERR_X509_INVALID_DATE + ret );
ansond 0:137634ff4186 134
ansond 0:137634ff4186 135 end = *p + len;
ansond 0:137634ff4186 136
ansond 0:137634ff4186 137 if( ( ret = x509_get_time( p, end, from ) ) != 0 )
ansond 0:137634ff4186 138 return( ret );
ansond 0:137634ff4186 139
ansond 0:137634ff4186 140 if( ( ret = x509_get_time( p, end, to ) ) != 0 )
ansond 0:137634ff4186 141 return( ret );
ansond 0:137634ff4186 142
ansond 0:137634ff4186 143 if( *p != end )
ansond 0:137634ff4186 144 return( POLARSSL_ERR_X509_INVALID_DATE +
ansond 0:137634ff4186 145 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
ansond 0:137634ff4186 146
ansond 0:137634ff4186 147 return( 0 );
ansond 0:137634ff4186 148 }
ansond 0:137634ff4186 149
ansond 0:137634ff4186 150 /*
ansond 0:137634ff4186 151 * X.509 v2/v3 unique identifier (not parsed)
ansond 0:137634ff4186 152 */
ansond 0:137634ff4186 153 static int x509_get_uid( unsigned char **p,
ansond 0:137634ff4186 154 const unsigned char *end,
ansond 0:137634ff4186 155 x509_buf *uid, int n )
ansond 0:137634ff4186 156 {
ansond 0:137634ff4186 157 int ret;
ansond 0:137634ff4186 158
ansond 0:137634ff4186 159 if( *p == end )
ansond 0:137634ff4186 160 return( 0 );
ansond 0:137634ff4186 161
ansond 0:137634ff4186 162 uid->tag = **p;
ansond 0:137634ff4186 163
ansond 0:137634ff4186 164 if( ( ret = asn1_get_tag( p, end, &uid->len,
ansond 0:137634ff4186 165 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | n ) ) != 0 )
ansond 0:137634ff4186 166 {
ansond 0:137634ff4186 167 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
ansond 0:137634ff4186 168 return( 0 );
ansond 0:137634ff4186 169
ansond 0:137634ff4186 170 return( ret );
ansond 0:137634ff4186 171 }
ansond 0:137634ff4186 172
ansond 0:137634ff4186 173 uid->p = *p;
ansond 0:137634ff4186 174 *p += uid->len;
ansond 0:137634ff4186 175
ansond 0:137634ff4186 176 return( 0 );
ansond 0:137634ff4186 177 }
ansond 0:137634ff4186 178
ansond 0:137634ff4186 179 static int x509_get_basic_constraints( unsigned char **p,
ansond 0:137634ff4186 180 const unsigned char *end,
ansond 0:137634ff4186 181 int *ca_istrue,
ansond 0:137634ff4186 182 int *max_pathlen )
ansond 0:137634ff4186 183 {
ansond 0:137634ff4186 184 int ret;
ansond 0:137634ff4186 185 size_t len;
ansond 0:137634ff4186 186
ansond 0:137634ff4186 187 /*
ansond 0:137634ff4186 188 * BasicConstraints ::= SEQUENCE {
ansond 0:137634ff4186 189 * cA BOOLEAN DEFAULT FALSE,
ansond 0:137634ff4186 190 * pathLenConstraint INTEGER (0..MAX) OPTIONAL }
ansond 0:137634ff4186 191 */
ansond 0:137634ff4186 192 *ca_istrue = 0; /* DEFAULT FALSE */
ansond 0:137634ff4186 193 *max_pathlen = 0; /* endless */
ansond 0:137634ff4186 194
ansond 0:137634ff4186 195 if( ( ret = asn1_get_tag( p, end, &len,
ansond 0:137634ff4186 196 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
ansond 0:137634ff4186 197 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
ansond 0:137634ff4186 198
ansond 0:137634ff4186 199 if( *p == end )
ansond 0:137634ff4186 200 return( 0 );
ansond 0:137634ff4186 201
ansond 0:137634ff4186 202 if( ( ret = asn1_get_bool( p, end, ca_istrue ) ) != 0 )
ansond 0:137634ff4186 203 {
ansond 0:137634ff4186 204 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
ansond 0:137634ff4186 205 ret = asn1_get_int( p, end, ca_istrue );
ansond 0:137634ff4186 206
ansond 0:137634ff4186 207 if( ret != 0 )
ansond 0:137634ff4186 208 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
ansond 0:137634ff4186 209
ansond 0:137634ff4186 210 if( *ca_istrue != 0 )
ansond 0:137634ff4186 211 *ca_istrue = 1;
ansond 0:137634ff4186 212 }
ansond 0:137634ff4186 213
ansond 0:137634ff4186 214 if( *p == end )
ansond 0:137634ff4186 215 return( 0 );
ansond 0:137634ff4186 216
ansond 0:137634ff4186 217 if( ( ret = asn1_get_int( p, end, max_pathlen ) ) != 0 )
ansond 0:137634ff4186 218 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
ansond 0:137634ff4186 219
ansond 0:137634ff4186 220 if( *p != end )
ansond 0:137634ff4186 221 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
ansond 0:137634ff4186 222 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
ansond 0:137634ff4186 223
ansond 0:137634ff4186 224 (*max_pathlen)++;
ansond 0:137634ff4186 225
ansond 0:137634ff4186 226 return( 0 );
ansond 0:137634ff4186 227 }
ansond 0:137634ff4186 228
ansond 0:137634ff4186 229 static int x509_get_ns_cert_type( unsigned char **p,
ansond 0:137634ff4186 230 const unsigned char *end,
ansond 0:137634ff4186 231 unsigned char *ns_cert_type)
ansond 0:137634ff4186 232 {
ansond 0:137634ff4186 233 int ret;
ansond 0:137634ff4186 234 x509_bitstring bs = { 0, 0, NULL };
ansond 0:137634ff4186 235
ansond 0:137634ff4186 236 if( ( ret = asn1_get_bitstring( p, end, &bs ) ) != 0 )
ansond 0:137634ff4186 237 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
ansond 0:137634ff4186 238
ansond 0:137634ff4186 239 if( bs.len != 1 )
ansond 0:137634ff4186 240 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
ansond 0:137634ff4186 241 POLARSSL_ERR_ASN1_INVALID_LENGTH );
ansond 0:137634ff4186 242
ansond 0:137634ff4186 243 /* Get actual bitstring */
ansond 0:137634ff4186 244 *ns_cert_type = *bs.p;
ansond 0:137634ff4186 245 return( 0 );
ansond 0:137634ff4186 246 }
ansond 0:137634ff4186 247
ansond 0:137634ff4186 248 static int x509_get_key_usage( unsigned char **p,
ansond 0:137634ff4186 249 const unsigned char *end,
ansond 0:137634ff4186 250 unsigned char *key_usage)
ansond 0:137634ff4186 251 {
ansond 0:137634ff4186 252 int ret;
ansond 0:137634ff4186 253 x509_bitstring bs = { 0, 0, NULL };
ansond 0:137634ff4186 254
ansond 0:137634ff4186 255 if( ( ret = asn1_get_bitstring( p, end, &bs ) ) != 0 )
ansond 0:137634ff4186 256 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
ansond 0:137634ff4186 257
ansond 0:137634ff4186 258 if( bs.len < 1 )
ansond 0:137634ff4186 259 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
ansond 0:137634ff4186 260 POLARSSL_ERR_ASN1_INVALID_LENGTH );
ansond 0:137634ff4186 261
ansond 0:137634ff4186 262 /* Get actual bitstring */
ansond 0:137634ff4186 263 *key_usage = *bs.p;
ansond 0:137634ff4186 264 return( 0 );
ansond 0:137634ff4186 265 }
ansond 0:137634ff4186 266
ansond 0:137634ff4186 267 /*
ansond 0:137634ff4186 268 * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
ansond 0:137634ff4186 269 *
ansond 0:137634ff4186 270 * KeyPurposeId ::= OBJECT IDENTIFIER
ansond 0:137634ff4186 271 */
ansond 0:137634ff4186 272 static int x509_get_ext_key_usage( unsigned char **p,
ansond 0:137634ff4186 273 const unsigned char *end,
ansond 0:137634ff4186 274 x509_sequence *ext_key_usage)
ansond 0:137634ff4186 275 {
ansond 0:137634ff4186 276 int ret;
ansond 0:137634ff4186 277
ansond 0:137634ff4186 278 if( ( ret = asn1_get_sequence_of( p, end, ext_key_usage, ASN1_OID ) ) != 0 )
ansond 0:137634ff4186 279 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
ansond 0:137634ff4186 280
ansond 0:137634ff4186 281 /* Sequence length must be >= 1 */
ansond 0:137634ff4186 282 if( ext_key_usage->buf.p == NULL )
ansond 0:137634ff4186 283 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
ansond 0:137634ff4186 284 POLARSSL_ERR_ASN1_INVALID_LENGTH );
ansond 0:137634ff4186 285
ansond 0:137634ff4186 286 return( 0 );
ansond 0:137634ff4186 287 }
ansond 0:137634ff4186 288
ansond 0:137634ff4186 289 /*
ansond 0:137634ff4186 290 * SubjectAltName ::= GeneralNames
ansond 0:137634ff4186 291 *
ansond 0:137634ff4186 292 * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
ansond 0:137634ff4186 293 *
ansond 0:137634ff4186 294 * GeneralName ::= CHOICE {
ansond 0:137634ff4186 295 * otherName [0] OtherName,
ansond 0:137634ff4186 296 * rfc822Name [1] IA5String,
ansond 0:137634ff4186 297 * dNSName [2] IA5String,
ansond 0:137634ff4186 298 * x400Address [3] ORAddress,
ansond 0:137634ff4186 299 * directoryName [4] Name,
ansond 0:137634ff4186 300 * ediPartyName [5] EDIPartyName,
ansond 0:137634ff4186 301 * uniformResourceIdentifier [6] IA5String,
ansond 0:137634ff4186 302 * iPAddress [7] OCTET STRING,
ansond 0:137634ff4186 303 * registeredID [8] OBJECT IDENTIFIER }
ansond 0:137634ff4186 304 *
ansond 0:137634ff4186 305 * OtherName ::= SEQUENCE {
ansond 0:137634ff4186 306 * type-id OBJECT IDENTIFIER,
ansond 0:137634ff4186 307 * value [0] EXPLICIT ANY DEFINED BY type-id }
ansond 0:137634ff4186 308 *
ansond 0:137634ff4186 309 * EDIPartyName ::= SEQUENCE {
ansond 0:137634ff4186 310 * nameAssigner [0] DirectoryString OPTIONAL,
ansond 0:137634ff4186 311 * partyName [1] DirectoryString }
ansond 0:137634ff4186 312 *
ansond 0:137634ff4186 313 * NOTE: we only parse and use dNSName at this point.
ansond 0:137634ff4186 314 */
ansond 0:137634ff4186 315 static int x509_get_subject_alt_name( unsigned char **p,
ansond 0:137634ff4186 316 const unsigned char *end,
ansond 0:137634ff4186 317 x509_sequence *subject_alt_name )
ansond 0:137634ff4186 318 {
ansond 0:137634ff4186 319 int ret;
ansond 0:137634ff4186 320 size_t len, tag_len;
ansond 0:137634ff4186 321 asn1_buf *buf;
ansond 0:137634ff4186 322 unsigned char tag;
ansond 0:137634ff4186 323 asn1_sequence *cur = subject_alt_name;
ansond 0:137634ff4186 324
ansond 0:137634ff4186 325 /* Get main sequence tag */
ansond 0:137634ff4186 326 if( ( ret = asn1_get_tag( p, end, &len,
ansond 0:137634ff4186 327 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
ansond 0:137634ff4186 328 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
ansond 0:137634ff4186 329
ansond 0:137634ff4186 330 if( *p + len != end )
ansond 0:137634ff4186 331 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
ansond 0:137634ff4186 332 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
ansond 0:137634ff4186 333
ansond 0:137634ff4186 334 while( *p < end )
ansond 0:137634ff4186 335 {
ansond 0:137634ff4186 336 if( ( end - *p ) < 1 )
ansond 0:137634ff4186 337 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
ansond 0:137634ff4186 338 POLARSSL_ERR_ASN1_OUT_OF_DATA );
ansond 0:137634ff4186 339
ansond 0:137634ff4186 340 tag = **p;
ansond 0:137634ff4186 341 (*p)++;
ansond 0:137634ff4186 342 if( ( ret = asn1_get_len( p, end, &tag_len ) ) != 0 )
ansond 0:137634ff4186 343 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
ansond 0:137634ff4186 344
ansond 0:137634ff4186 345 if( ( tag & ASN1_CONTEXT_SPECIFIC ) != ASN1_CONTEXT_SPECIFIC )
ansond 0:137634ff4186 346 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
ansond 0:137634ff4186 347 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
ansond 0:137634ff4186 348
ansond 0:137634ff4186 349 /* Skip everything but DNS name */
ansond 0:137634ff4186 350 if( tag != ( ASN1_CONTEXT_SPECIFIC | 2 ) )
ansond 0:137634ff4186 351 {
ansond 0:137634ff4186 352 *p += tag_len;
ansond 0:137634ff4186 353 continue;
ansond 0:137634ff4186 354 }
ansond 0:137634ff4186 355
ansond 0:137634ff4186 356 /* Allocate and assign next pointer */
ansond 0:137634ff4186 357 if( cur->buf.p != NULL )
ansond 0:137634ff4186 358 {
ansond 0:137634ff4186 359 if( cur->next != NULL )
ansond 0:137634ff4186 360 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS );
ansond 0:137634ff4186 361
ansond 0:137634ff4186 362 cur->next = polarssl_malloc( sizeof( asn1_sequence ) );
ansond 0:137634ff4186 363
ansond 0:137634ff4186 364 if( cur->next == NULL )
ansond 0:137634ff4186 365 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
ansond 0:137634ff4186 366 POLARSSL_ERR_ASN1_MALLOC_FAILED );
ansond 0:137634ff4186 367
ansond 0:137634ff4186 368 memset( cur->next, 0, sizeof( asn1_sequence ) );
ansond 0:137634ff4186 369 cur = cur->next;
ansond 0:137634ff4186 370 }
ansond 0:137634ff4186 371
ansond 0:137634ff4186 372 buf = &(cur->buf);
ansond 0:137634ff4186 373 buf->tag = tag;
ansond 0:137634ff4186 374 buf->p = *p;
ansond 0:137634ff4186 375 buf->len = tag_len;
ansond 0:137634ff4186 376 *p += buf->len;
ansond 0:137634ff4186 377 }
ansond 0:137634ff4186 378
ansond 0:137634ff4186 379 /* Set final sequence entry's next pointer to NULL */
ansond 0:137634ff4186 380 cur->next = NULL;
ansond 0:137634ff4186 381
ansond 0:137634ff4186 382 if( *p != end )
ansond 0:137634ff4186 383 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
ansond 0:137634ff4186 384 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
ansond 0:137634ff4186 385
ansond 0:137634ff4186 386 return( 0 );
ansond 0:137634ff4186 387 }
ansond 0:137634ff4186 388
ansond 0:137634ff4186 389 /*
ansond 0:137634ff4186 390 * X.509 v3 extensions
ansond 0:137634ff4186 391 *
ansond 0:137634ff4186 392 * TODO: Perform all of the basic constraints tests required by the RFC
ansond 0:137634ff4186 393 * TODO: Set values for undetected extensions to a sane default?
ansond 0:137634ff4186 394 *
ansond 0:137634ff4186 395 */
ansond 0:137634ff4186 396 static int x509_get_crt_ext( unsigned char **p,
ansond 0:137634ff4186 397 const unsigned char *end,
ansond 0:137634ff4186 398 x509_crt *crt )
ansond 0:137634ff4186 399 {
ansond 0:137634ff4186 400 int ret;
ansond 0:137634ff4186 401 size_t len;
ansond 0:137634ff4186 402 unsigned char *end_ext_data, *end_ext_octet;
ansond 0:137634ff4186 403
ansond 0:137634ff4186 404 if( ( ret = x509_get_ext( p, end, &crt->v3_ext, 3 ) ) != 0 )
ansond 0:137634ff4186 405 {
ansond 0:137634ff4186 406 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
ansond 0:137634ff4186 407 return( 0 );
ansond 0:137634ff4186 408
ansond 0:137634ff4186 409 return( ret );
ansond 0:137634ff4186 410 }
ansond 0:137634ff4186 411
ansond 0:137634ff4186 412 while( *p < end )
ansond 0:137634ff4186 413 {
ansond 0:137634ff4186 414 /*
ansond 0:137634ff4186 415 * Extension ::= SEQUENCE {
ansond 0:137634ff4186 416 * extnID OBJECT IDENTIFIER,
ansond 0:137634ff4186 417 * critical BOOLEAN DEFAULT FALSE,
ansond 0:137634ff4186 418 * extnValue OCTET STRING }
ansond 0:137634ff4186 419 */
ansond 0:137634ff4186 420 x509_buf extn_oid = {0, 0, NULL};
ansond 0:137634ff4186 421 int is_critical = 0; /* DEFAULT FALSE */
ansond 0:137634ff4186 422 int ext_type = 0;
ansond 0:137634ff4186 423
ansond 0:137634ff4186 424 if( ( ret = asn1_get_tag( p, end, &len,
ansond 0:137634ff4186 425 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
ansond 0:137634ff4186 426 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
ansond 0:137634ff4186 427
ansond 0:137634ff4186 428 end_ext_data = *p + len;
ansond 0:137634ff4186 429
ansond 0:137634ff4186 430 /* Get extension ID */
ansond 0:137634ff4186 431 extn_oid.tag = **p;
ansond 0:137634ff4186 432
ansond 0:137634ff4186 433 if( ( ret = asn1_get_tag( p, end, &extn_oid.len, ASN1_OID ) ) != 0 )
ansond 0:137634ff4186 434 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
ansond 0:137634ff4186 435
ansond 0:137634ff4186 436 extn_oid.p = *p;
ansond 0:137634ff4186 437 *p += extn_oid.len;
ansond 0:137634ff4186 438
ansond 0:137634ff4186 439 if( ( end - *p ) < 1 )
ansond 0:137634ff4186 440 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
ansond 0:137634ff4186 441 POLARSSL_ERR_ASN1_OUT_OF_DATA );
ansond 0:137634ff4186 442
ansond 0:137634ff4186 443 /* Get optional critical */
ansond 0:137634ff4186 444 if( ( ret = asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 &&
ansond 0:137634ff4186 445 ( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) )
ansond 0:137634ff4186 446 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
ansond 0:137634ff4186 447
ansond 0:137634ff4186 448 /* Data should be octet string type */
ansond 0:137634ff4186 449 if( ( ret = asn1_get_tag( p, end_ext_data, &len,
ansond 0:137634ff4186 450 ASN1_OCTET_STRING ) ) != 0 )
ansond 0:137634ff4186 451 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
ansond 0:137634ff4186 452
ansond 0:137634ff4186 453 end_ext_octet = *p + len;
ansond 0:137634ff4186 454
ansond 0:137634ff4186 455 if( end_ext_octet != end_ext_data )
ansond 0:137634ff4186 456 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
ansond 0:137634ff4186 457 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
ansond 0:137634ff4186 458
ansond 0:137634ff4186 459 /*
ansond 0:137634ff4186 460 * Detect supported extensions
ansond 0:137634ff4186 461 */
ansond 0:137634ff4186 462 ret = oid_get_x509_ext_type( &extn_oid, &ext_type );
ansond 0:137634ff4186 463
ansond 0:137634ff4186 464 if( ret != 0 )
ansond 0:137634ff4186 465 {
ansond 0:137634ff4186 466 /* No parser found, skip extension */
ansond 0:137634ff4186 467 *p = end_ext_octet;
ansond 0:137634ff4186 468
ansond 0:137634ff4186 469 #if !defined(POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
ansond 0:137634ff4186 470 if( is_critical )
ansond 0:137634ff4186 471 {
ansond 0:137634ff4186 472 /* Data is marked as critical: fail */
ansond 0:137634ff4186 473 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
ansond 0:137634ff4186 474 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
ansond 0:137634ff4186 475 }
ansond 0:137634ff4186 476 #endif
ansond 0:137634ff4186 477 continue;
ansond 0:137634ff4186 478 }
ansond 0:137634ff4186 479
ansond 0:137634ff4186 480 /* Forbid repeated extensions */
ansond 0:137634ff4186 481 if( ( crt->ext_types & ext_type ) != 0 )
ansond 0:137634ff4186 482 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS );
ansond 0:137634ff4186 483
ansond 0:137634ff4186 484 crt->ext_types |= ext_type;
ansond 0:137634ff4186 485
ansond 0:137634ff4186 486 switch( ext_type )
ansond 0:137634ff4186 487 {
ansond 0:137634ff4186 488 case EXT_BASIC_CONSTRAINTS:
ansond 0:137634ff4186 489 /* Parse basic constraints */
ansond 0:137634ff4186 490 if( ( ret = x509_get_basic_constraints( p, end_ext_octet,
ansond 0:137634ff4186 491 &crt->ca_istrue, &crt->max_pathlen ) ) != 0 )
ansond 0:137634ff4186 492 return( ret );
ansond 0:137634ff4186 493 break;
ansond 0:137634ff4186 494
ansond 0:137634ff4186 495 case EXT_KEY_USAGE:
ansond 0:137634ff4186 496 /* Parse key usage */
ansond 0:137634ff4186 497 if( ( ret = x509_get_key_usage( p, end_ext_octet,
ansond 0:137634ff4186 498 &crt->key_usage ) ) != 0 )
ansond 0:137634ff4186 499 return( ret );
ansond 0:137634ff4186 500 break;
ansond 0:137634ff4186 501
ansond 0:137634ff4186 502 case EXT_EXTENDED_KEY_USAGE:
ansond 0:137634ff4186 503 /* Parse extended key usage */
ansond 0:137634ff4186 504 if( ( ret = x509_get_ext_key_usage( p, end_ext_octet,
ansond 0:137634ff4186 505 &crt->ext_key_usage ) ) != 0 )
ansond 0:137634ff4186 506 return( ret );
ansond 0:137634ff4186 507 break;
ansond 0:137634ff4186 508
ansond 0:137634ff4186 509 case EXT_SUBJECT_ALT_NAME:
ansond 0:137634ff4186 510 /* Parse subject alt name */
ansond 0:137634ff4186 511 if( ( ret = x509_get_subject_alt_name( p, end_ext_octet,
ansond 0:137634ff4186 512 &crt->subject_alt_names ) ) != 0 )
ansond 0:137634ff4186 513 return( ret );
ansond 0:137634ff4186 514 break;
ansond 0:137634ff4186 515
ansond 0:137634ff4186 516 case EXT_NS_CERT_TYPE:
ansond 0:137634ff4186 517 /* Parse netscape certificate type */
ansond 0:137634ff4186 518 if( ( ret = x509_get_ns_cert_type( p, end_ext_octet,
ansond 0:137634ff4186 519 &crt->ns_cert_type ) ) != 0 )
ansond 0:137634ff4186 520 return( ret );
ansond 0:137634ff4186 521 break;
ansond 0:137634ff4186 522
ansond 0:137634ff4186 523 default:
ansond 0:137634ff4186 524 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
ansond 0:137634ff4186 525 }
ansond 0:137634ff4186 526 }
ansond 0:137634ff4186 527
ansond 0:137634ff4186 528 if( *p != end )
ansond 0:137634ff4186 529 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
ansond 0:137634ff4186 530 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
ansond 0:137634ff4186 531
ansond 0:137634ff4186 532 return( 0 );
ansond 0:137634ff4186 533 }
ansond 0:137634ff4186 534
ansond 0:137634ff4186 535 /*
ansond 0:137634ff4186 536 * Parse and fill a single X.509 certificate in DER format
ansond 0:137634ff4186 537 */
ansond 0:137634ff4186 538 static int x509_crt_parse_der_core( x509_crt *crt, const unsigned char *buf,
ansond 0:137634ff4186 539 size_t buflen )
ansond 0:137634ff4186 540 {
ansond 0:137634ff4186 541 int ret;
ansond 0:137634ff4186 542 size_t len;
ansond 0:137634ff4186 543 unsigned char *p, *end, *crt_end;
ansond 0:137634ff4186 544 x509_buf sig_params1, sig_params2;
ansond 0:137634ff4186 545
ansond 0:137634ff4186 546 memset( &sig_params1, 0, sizeof( x509_buf ) );
ansond 0:137634ff4186 547 memset( &sig_params2, 0, sizeof( x509_buf ) );
ansond 0:137634ff4186 548
ansond 0:137634ff4186 549 /*
ansond 0:137634ff4186 550 * Check for valid input
ansond 0:137634ff4186 551 */
ansond 0:137634ff4186 552 if( crt == NULL || buf == NULL )
ansond 0:137634ff4186 553 return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
ansond 0:137634ff4186 554
ansond 0:137634ff4186 555 p = polarssl_malloc( len = buflen );
ansond 0:137634ff4186 556
ansond 0:137634ff4186 557 if( p == NULL )
ansond 0:137634ff4186 558 return( POLARSSL_ERR_X509_MALLOC_FAILED );
ansond 0:137634ff4186 559
ansond 0:137634ff4186 560 memcpy( p, buf, buflen );
ansond 0:137634ff4186 561
ansond 0:137634ff4186 562 crt->raw.p = p;
ansond 0:137634ff4186 563 crt->raw.len = len;
ansond 0:137634ff4186 564 end = p + len;
ansond 0:137634ff4186 565
ansond 0:137634ff4186 566 /*
ansond 0:137634ff4186 567 * Certificate ::= SEQUENCE {
ansond 0:137634ff4186 568 * tbsCertificate TBSCertificate,
ansond 0:137634ff4186 569 * signatureAlgorithm AlgorithmIdentifier,
ansond 0:137634ff4186 570 * signatureValue BIT STRING }
ansond 0:137634ff4186 571 */
ansond 0:137634ff4186 572 if( ( ret = asn1_get_tag( &p, end, &len,
ansond 0:137634ff4186 573 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
ansond 0:137634ff4186 574 {
ansond 0:137634ff4186 575 x509_crt_free( crt );
ansond 0:137634ff4186 576 return( POLARSSL_ERR_X509_INVALID_FORMAT );
ansond 0:137634ff4186 577 }
ansond 0:137634ff4186 578
ansond 0:137634ff4186 579 if( len > (size_t) ( end - p ) )
ansond 0:137634ff4186 580 {
ansond 0:137634ff4186 581 x509_crt_free( crt );
ansond 0:137634ff4186 582 return( POLARSSL_ERR_X509_INVALID_FORMAT +
ansond 0:137634ff4186 583 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
ansond 0:137634ff4186 584 }
ansond 0:137634ff4186 585 crt_end = p + len;
ansond 0:137634ff4186 586
ansond 0:137634ff4186 587 /*
ansond 0:137634ff4186 588 * TBSCertificate ::= SEQUENCE {
ansond 0:137634ff4186 589 */
ansond 0:137634ff4186 590 crt->tbs.p = p;
ansond 0:137634ff4186 591
ansond 0:137634ff4186 592 if( ( ret = asn1_get_tag( &p, end, &len,
ansond 0:137634ff4186 593 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
ansond 0:137634ff4186 594 {
ansond 0:137634ff4186 595 x509_crt_free( crt );
ansond 0:137634ff4186 596 return( POLARSSL_ERR_X509_INVALID_FORMAT + ret );
ansond 0:137634ff4186 597 }
ansond 0:137634ff4186 598
ansond 0:137634ff4186 599 end = p + len;
ansond 0:137634ff4186 600 crt->tbs.len = end - crt->tbs.p;
ansond 0:137634ff4186 601
ansond 0:137634ff4186 602 /*
ansond 0:137634ff4186 603 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
ansond 0:137634ff4186 604 *
ansond 0:137634ff4186 605 * CertificateSerialNumber ::= INTEGER
ansond 0:137634ff4186 606 *
ansond 0:137634ff4186 607 * signature AlgorithmIdentifier
ansond 0:137634ff4186 608 */
ansond 0:137634ff4186 609 if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 ||
ansond 0:137634ff4186 610 ( ret = x509_get_serial( &p, end, &crt->serial ) ) != 0 ||
ansond 0:137634ff4186 611 ( ret = x509_get_alg( &p, end, &crt->sig_oid1,
ansond 0:137634ff4186 612 &sig_params1 ) ) != 0 )
ansond 0:137634ff4186 613 {
ansond 0:137634ff4186 614 x509_crt_free( crt );
ansond 0:137634ff4186 615 return( ret );
ansond 0:137634ff4186 616 }
ansond 0:137634ff4186 617
ansond 0:137634ff4186 618 crt->version++;
ansond 0:137634ff4186 619
ansond 0:137634ff4186 620 if( crt->version > 3 )
ansond 0:137634ff4186 621 {
ansond 0:137634ff4186 622 x509_crt_free( crt );
ansond 0:137634ff4186 623 return( POLARSSL_ERR_X509_UNKNOWN_VERSION );
ansond 0:137634ff4186 624 }
ansond 0:137634ff4186 625
ansond 0:137634ff4186 626 if( ( ret = x509_get_sig_alg( &crt->sig_oid1, &sig_params1,
ansond 0:137634ff4186 627 &crt->sig_md, &crt->sig_pk,
ansond 0:137634ff4186 628 &crt->sig_opts ) ) != 0 )
ansond 0:137634ff4186 629 {
ansond 0:137634ff4186 630 x509_crt_free( crt );
ansond 0:137634ff4186 631 return( ret );
ansond 0:137634ff4186 632 }
ansond 0:137634ff4186 633
ansond 0:137634ff4186 634 /*
ansond 0:137634ff4186 635 * issuer Name
ansond 0:137634ff4186 636 */
ansond 0:137634ff4186 637 crt->issuer_raw.p = p;
ansond 0:137634ff4186 638
ansond 0:137634ff4186 639 if( ( ret = asn1_get_tag( &p, end, &len,
ansond 0:137634ff4186 640 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
ansond 0:137634ff4186 641 {
ansond 0:137634ff4186 642 x509_crt_free( crt );
ansond 0:137634ff4186 643 return( POLARSSL_ERR_X509_INVALID_FORMAT + ret );
ansond 0:137634ff4186 644 }
ansond 0:137634ff4186 645
ansond 0:137634ff4186 646 if( ( ret = x509_get_name( &p, p + len, &crt->issuer ) ) != 0 )
ansond 0:137634ff4186 647 {
ansond 0:137634ff4186 648 x509_crt_free( crt );
ansond 0:137634ff4186 649 return( ret );
ansond 0:137634ff4186 650 }
ansond 0:137634ff4186 651
ansond 0:137634ff4186 652 crt->issuer_raw.len = p - crt->issuer_raw.p;
ansond 0:137634ff4186 653
ansond 0:137634ff4186 654 /*
ansond 0:137634ff4186 655 * Validity ::= SEQUENCE {
ansond 0:137634ff4186 656 * notBefore Time,
ansond 0:137634ff4186 657 * notAfter Time }
ansond 0:137634ff4186 658 *
ansond 0:137634ff4186 659 */
ansond 0:137634ff4186 660 if( ( ret = x509_get_dates( &p, end, &crt->valid_from,
ansond 0:137634ff4186 661 &crt->valid_to ) ) != 0 )
ansond 0:137634ff4186 662 {
ansond 0:137634ff4186 663 x509_crt_free( crt );
ansond 0:137634ff4186 664 return( ret );
ansond 0:137634ff4186 665 }
ansond 0:137634ff4186 666
ansond 0:137634ff4186 667 /*
ansond 0:137634ff4186 668 * subject Name
ansond 0:137634ff4186 669 */
ansond 0:137634ff4186 670 crt->subject_raw.p = p;
ansond 0:137634ff4186 671
ansond 0:137634ff4186 672 if( ( ret = asn1_get_tag( &p, end, &len,
ansond 0:137634ff4186 673 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
ansond 0:137634ff4186 674 {
ansond 0:137634ff4186 675 x509_crt_free( crt );
ansond 0:137634ff4186 676 return( POLARSSL_ERR_X509_INVALID_FORMAT + ret );
ansond 0:137634ff4186 677 }
ansond 0:137634ff4186 678
ansond 0:137634ff4186 679 if( len && ( ret = x509_get_name( &p, p + len, &crt->subject ) ) != 0 )
ansond 0:137634ff4186 680 {
ansond 0:137634ff4186 681 x509_crt_free( crt );
ansond 0:137634ff4186 682 return( ret );
ansond 0:137634ff4186 683 }
ansond 0:137634ff4186 684
ansond 0:137634ff4186 685 crt->subject_raw.len = p - crt->subject_raw.p;
ansond 0:137634ff4186 686
ansond 0:137634ff4186 687 /*
ansond 0:137634ff4186 688 * SubjectPublicKeyInfo
ansond 0:137634ff4186 689 */
ansond 0:137634ff4186 690 if( ( ret = pk_parse_subpubkey( &p, end, &crt->pk ) ) != 0 )
ansond 0:137634ff4186 691 {
ansond 0:137634ff4186 692 x509_crt_free( crt );
ansond 0:137634ff4186 693 return( ret );
ansond 0:137634ff4186 694 }
ansond 0:137634ff4186 695
ansond 0:137634ff4186 696 /*
ansond 0:137634ff4186 697 * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
ansond 0:137634ff4186 698 * -- If present, version shall be v2 or v3
ansond 0:137634ff4186 699 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
ansond 0:137634ff4186 700 * -- If present, version shall be v2 or v3
ansond 0:137634ff4186 701 * extensions [3] EXPLICIT Extensions OPTIONAL
ansond 0:137634ff4186 702 * -- If present, version shall be v3
ansond 0:137634ff4186 703 */
ansond 0:137634ff4186 704 if( crt->version == 2 || crt->version == 3 )
ansond 0:137634ff4186 705 {
ansond 0:137634ff4186 706 ret = x509_get_uid( &p, end, &crt->issuer_id, 1 );
ansond 0:137634ff4186 707 if( ret != 0 )
ansond 0:137634ff4186 708 {
ansond 0:137634ff4186 709 x509_crt_free( crt );
ansond 0:137634ff4186 710 return( ret );
ansond 0:137634ff4186 711 }
ansond 0:137634ff4186 712 }
ansond 0:137634ff4186 713
ansond 0:137634ff4186 714 if( crt->version == 2 || crt->version == 3 )
ansond 0:137634ff4186 715 {
ansond 0:137634ff4186 716 ret = x509_get_uid( &p, end, &crt->subject_id, 2 );
ansond 0:137634ff4186 717 if( ret != 0 )
ansond 0:137634ff4186 718 {
ansond 0:137634ff4186 719 x509_crt_free( crt );
ansond 0:137634ff4186 720 return( ret );
ansond 0:137634ff4186 721 }
ansond 0:137634ff4186 722 }
ansond 0:137634ff4186 723
ansond 0:137634ff4186 724 #if !defined(POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3)
ansond 0:137634ff4186 725 if( crt->version == 3 )
ansond 0:137634ff4186 726 {
ansond 0:137634ff4186 727 #endif
ansond 0:137634ff4186 728 ret = x509_get_crt_ext( &p, end, crt );
ansond 0:137634ff4186 729 if( ret != 0 )
ansond 0:137634ff4186 730 {
ansond 0:137634ff4186 731 x509_crt_free( crt );
ansond 0:137634ff4186 732 return( ret );
ansond 0:137634ff4186 733 }
ansond 0:137634ff4186 734 #if !defined(POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3)
ansond 0:137634ff4186 735 }
ansond 0:137634ff4186 736 #endif
ansond 0:137634ff4186 737
ansond 0:137634ff4186 738 if( p != end )
ansond 0:137634ff4186 739 {
ansond 0:137634ff4186 740 x509_crt_free( crt );
ansond 0:137634ff4186 741 return( POLARSSL_ERR_X509_INVALID_FORMAT +
ansond 0:137634ff4186 742 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
ansond 0:137634ff4186 743 }
ansond 0:137634ff4186 744
ansond 0:137634ff4186 745 end = crt_end;
ansond 0:137634ff4186 746
ansond 0:137634ff4186 747 /*
ansond 0:137634ff4186 748 * }
ansond 0:137634ff4186 749 * -- end of TBSCertificate
ansond 0:137634ff4186 750 *
ansond 0:137634ff4186 751 * signatureAlgorithm AlgorithmIdentifier,
ansond 0:137634ff4186 752 * signatureValue BIT STRING
ansond 0:137634ff4186 753 */
ansond 0:137634ff4186 754 if( ( ret = x509_get_alg( &p, end, &crt->sig_oid2, &sig_params2 ) ) != 0 )
ansond 0:137634ff4186 755 {
ansond 0:137634ff4186 756 x509_crt_free( crt );
ansond 0:137634ff4186 757 return( ret );
ansond 0:137634ff4186 758 }
ansond 0:137634ff4186 759
ansond 0:137634ff4186 760 if( crt->sig_oid1.len != crt->sig_oid2.len ||
ansond 0:137634ff4186 761 memcmp( crt->sig_oid1.p, crt->sig_oid2.p, crt->sig_oid1.len ) != 0 ||
ansond 0:137634ff4186 762 sig_params1.len != sig_params2.len ||
ansond 0:137634ff4186 763 ( sig_params1.len != 0 &&
ansond 0:137634ff4186 764 memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) )
ansond 0:137634ff4186 765 {
ansond 0:137634ff4186 766 x509_crt_free( crt );
ansond 0:137634ff4186 767 return( POLARSSL_ERR_X509_SIG_MISMATCH );
ansond 0:137634ff4186 768 }
ansond 0:137634ff4186 769
ansond 0:137634ff4186 770 if( ( ret = x509_get_sig( &p, end, &crt->sig ) ) != 0 )
ansond 0:137634ff4186 771 {
ansond 0:137634ff4186 772 x509_crt_free( crt );
ansond 0:137634ff4186 773 return( ret );
ansond 0:137634ff4186 774 }
ansond 0:137634ff4186 775
ansond 0:137634ff4186 776 if( p != end )
ansond 0:137634ff4186 777 {
ansond 0:137634ff4186 778 x509_crt_free( crt );
ansond 0:137634ff4186 779 return( POLARSSL_ERR_X509_INVALID_FORMAT +
ansond 0:137634ff4186 780 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
ansond 0:137634ff4186 781 }
ansond 0:137634ff4186 782
ansond 0:137634ff4186 783 return( 0 );
ansond 0:137634ff4186 784 }
ansond 0:137634ff4186 785
ansond 0:137634ff4186 786 /*
ansond 0:137634ff4186 787 * Parse one X.509 certificate in DER format from a buffer and add them to a
ansond 0:137634ff4186 788 * chained list
ansond 0:137634ff4186 789 */
ansond 0:137634ff4186 790 int x509_crt_parse_der( x509_crt *chain, const unsigned char *buf,
ansond 0:137634ff4186 791 size_t buflen )
ansond 0:137634ff4186 792 {
ansond 0:137634ff4186 793 int ret;
ansond 0:137634ff4186 794 x509_crt *crt = chain, *prev = NULL;
ansond 0:137634ff4186 795
ansond 0:137634ff4186 796 /*
ansond 0:137634ff4186 797 * Check for valid input
ansond 0:137634ff4186 798 */
ansond 0:137634ff4186 799 if( crt == NULL || buf == NULL )
ansond 0:137634ff4186 800 return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
ansond 0:137634ff4186 801
ansond 0:137634ff4186 802 while( crt->version != 0 && crt->next != NULL )
ansond 0:137634ff4186 803 {
ansond 0:137634ff4186 804 prev = crt;
ansond 0:137634ff4186 805 crt = crt->next;
ansond 0:137634ff4186 806 }
ansond 0:137634ff4186 807
ansond 0:137634ff4186 808 /*
ansond 0:137634ff4186 809 * Add new certificate on the end of the chain if needed.
ansond 0:137634ff4186 810 */
ansond 0:137634ff4186 811 if( crt->version != 0 && crt->next == NULL )
ansond 0:137634ff4186 812 {
ansond 0:137634ff4186 813 crt->next = polarssl_malloc( sizeof( x509_crt ) );
ansond 0:137634ff4186 814
ansond 0:137634ff4186 815 if( crt->next == NULL )
ansond 0:137634ff4186 816 return( POLARSSL_ERR_X509_MALLOC_FAILED );
ansond 0:137634ff4186 817
ansond 0:137634ff4186 818 prev = crt;
ansond 0:137634ff4186 819 x509_crt_init( crt->next );
ansond 0:137634ff4186 820 crt = crt->next;
ansond 0:137634ff4186 821 }
ansond 0:137634ff4186 822
ansond 0:137634ff4186 823 if( ( ret = x509_crt_parse_der_core( crt, buf, buflen ) ) != 0 )
ansond 0:137634ff4186 824 {
ansond 0:137634ff4186 825 if( prev )
ansond 0:137634ff4186 826 prev->next = NULL;
ansond 0:137634ff4186 827
ansond 0:137634ff4186 828 if( crt != chain )
ansond 0:137634ff4186 829 polarssl_free( crt );
ansond 0:137634ff4186 830
ansond 0:137634ff4186 831 return( ret );
ansond 0:137634ff4186 832 }
ansond 0:137634ff4186 833
ansond 0:137634ff4186 834 return( 0 );
ansond 0:137634ff4186 835 }
ansond 0:137634ff4186 836
ansond 0:137634ff4186 837 /*
ansond 0:137634ff4186 838 * Parse one or more PEM certificates from a buffer and add them to the chained
ansond 0:137634ff4186 839 * list
ansond 0:137634ff4186 840 */
ansond 0:137634ff4186 841 int x509_crt_parse( x509_crt *chain, const unsigned char *buf, size_t buflen )
ansond 0:137634ff4186 842 {
ansond 0:137634ff4186 843 int success = 0, first_error = 0, total_failed = 0;
ansond 0:137634ff4186 844 int buf_format = X509_FORMAT_DER;
ansond 0:137634ff4186 845
ansond 0:137634ff4186 846 /*
ansond 0:137634ff4186 847 * Check for valid input
ansond 0:137634ff4186 848 */
ansond 0:137634ff4186 849 if( chain == NULL || buf == NULL )
ansond 0:137634ff4186 850 return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
ansond 0:137634ff4186 851
ansond 0:137634ff4186 852 /*
ansond 0:137634ff4186 853 * Determine buffer content. Buffer contains either one DER certificate or
ansond 0:137634ff4186 854 * one or more PEM certificates.
ansond 0:137634ff4186 855 */
ansond 0:137634ff4186 856 #if defined(POLARSSL_PEM_PARSE_C)
ansond 0:137634ff4186 857 if( strstr( (const char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL )
ansond 0:137634ff4186 858 buf_format = X509_FORMAT_PEM;
ansond 0:137634ff4186 859 #endif
ansond 0:137634ff4186 860
ansond 0:137634ff4186 861 if( buf_format == X509_FORMAT_DER )
ansond 0:137634ff4186 862 return x509_crt_parse_der( chain, buf, buflen );
ansond 0:137634ff4186 863
ansond 0:137634ff4186 864 #if defined(POLARSSL_PEM_PARSE_C)
ansond 0:137634ff4186 865 if( buf_format == X509_FORMAT_PEM )
ansond 0:137634ff4186 866 {
ansond 0:137634ff4186 867 int ret;
ansond 0:137634ff4186 868 pem_context pem;
ansond 0:137634ff4186 869
ansond 0:137634ff4186 870 while( buflen > 0 )
ansond 0:137634ff4186 871 {
ansond 0:137634ff4186 872 size_t use_len;
ansond 0:137634ff4186 873 pem_init( &pem );
ansond 0:137634ff4186 874
ansond 0:137634ff4186 875 ret = pem_read_buffer( &pem,
ansond 0:137634ff4186 876 "-----BEGIN CERTIFICATE-----",
ansond 0:137634ff4186 877 "-----END CERTIFICATE-----",
ansond 0:137634ff4186 878 buf, NULL, 0, &use_len );
ansond 0:137634ff4186 879
ansond 0:137634ff4186 880 if( ret == 0 )
ansond 0:137634ff4186 881 {
ansond 0:137634ff4186 882 /*
ansond 0:137634ff4186 883 * Was PEM encoded
ansond 0:137634ff4186 884 */
ansond 0:137634ff4186 885 buflen -= use_len;
ansond 0:137634ff4186 886 buf += use_len;
ansond 0:137634ff4186 887 }
ansond 0:137634ff4186 888 else if( ret == POLARSSL_ERR_PEM_BAD_INPUT_DATA )
ansond 0:137634ff4186 889 {
ansond 0:137634ff4186 890 return( ret );
ansond 0:137634ff4186 891 }
ansond 0:137634ff4186 892 else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
ansond 0:137634ff4186 893 {
ansond 0:137634ff4186 894 pem_free( &pem );
ansond 0:137634ff4186 895
ansond 0:137634ff4186 896 /*
ansond 0:137634ff4186 897 * PEM header and footer were found
ansond 0:137634ff4186 898 */
ansond 0:137634ff4186 899 buflen -= use_len;
ansond 0:137634ff4186 900 buf += use_len;
ansond 0:137634ff4186 901
ansond 0:137634ff4186 902 if( first_error == 0 )
ansond 0:137634ff4186 903 first_error = ret;
ansond 0:137634ff4186 904
ansond 0:137634ff4186 905 total_failed++;
ansond 0:137634ff4186 906 continue;
ansond 0:137634ff4186 907 }
ansond 0:137634ff4186 908 else
ansond 0:137634ff4186 909 break;
ansond 0:137634ff4186 910
ansond 0:137634ff4186 911 ret = x509_crt_parse_der( chain, pem.buf, pem.buflen );
ansond 0:137634ff4186 912
ansond 0:137634ff4186 913 pem_free( &pem );
ansond 0:137634ff4186 914
ansond 0:137634ff4186 915 if( ret != 0 )
ansond 0:137634ff4186 916 {
ansond 0:137634ff4186 917 /*
ansond 0:137634ff4186 918 * Quit parsing on a memory error
ansond 0:137634ff4186 919 */
ansond 0:137634ff4186 920 if( ret == POLARSSL_ERR_X509_MALLOC_FAILED )
ansond 0:137634ff4186 921 return( ret );
ansond 0:137634ff4186 922
ansond 0:137634ff4186 923 if( first_error == 0 )
ansond 0:137634ff4186 924 first_error = ret;
ansond 0:137634ff4186 925
ansond 0:137634ff4186 926 total_failed++;
ansond 0:137634ff4186 927 continue;
ansond 0:137634ff4186 928 }
ansond 0:137634ff4186 929
ansond 0:137634ff4186 930 success = 1;
ansond 0:137634ff4186 931 }
ansond 0:137634ff4186 932 }
ansond 0:137634ff4186 933 #endif /* POLARSSL_PEM_PARSE_C */
ansond 0:137634ff4186 934
ansond 0:137634ff4186 935 if( success )
ansond 0:137634ff4186 936 return( total_failed );
ansond 0:137634ff4186 937 else if( first_error )
ansond 0:137634ff4186 938 return( first_error );
ansond 0:137634ff4186 939 else
ansond 0:137634ff4186 940 return( POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT );
ansond 0:137634ff4186 941 }
ansond 0:137634ff4186 942
ansond 0:137634ff4186 943 #if defined(POLARSSL_FS_IO)
ansond 0:137634ff4186 944 /*
ansond 0:137634ff4186 945 * Load one or more certificates and add them to the chained list
ansond 0:137634ff4186 946 */
ansond 0:137634ff4186 947 int x509_crt_parse_file( x509_crt *chain, const char *path )
ansond 0:137634ff4186 948 {
ansond 0:137634ff4186 949 int ret;
ansond 0:137634ff4186 950 size_t n;
ansond 0:137634ff4186 951 unsigned char *buf;
ansond 0:137634ff4186 952
ansond 0:137634ff4186 953 if( ( ret = pk_load_file( path, &buf, &n ) ) != 0 )
ansond 0:137634ff4186 954 return( ret );
ansond 0:137634ff4186 955
ansond 0:137634ff4186 956 ret = x509_crt_parse( chain, buf, n );
ansond 0:137634ff4186 957
ansond 0:137634ff4186 958 polarssl_zeroize( buf, n + 1 );
ansond 0:137634ff4186 959 polarssl_free( buf );
ansond 0:137634ff4186 960
ansond 0:137634ff4186 961 return( ret );
ansond 0:137634ff4186 962 }
ansond 0:137634ff4186 963
ansond 0:137634ff4186 964 #if defined(POLARSSL_THREADING_PTHREAD)
ansond 0:137634ff4186 965 static threading_mutex_t readdir_mutex = PTHREAD_MUTEX_INITIALIZER;
ansond 0:137634ff4186 966 #endif
ansond 0:137634ff4186 967
ansond 0:137634ff4186 968 int x509_crt_parse_path( x509_crt *chain, const char *path )
ansond 0:137634ff4186 969 {
ansond 0:137634ff4186 970 int ret = 0;
ansond 0:137634ff4186 971 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
ansond 0:137634ff4186 972 int w_ret;
ansond 0:137634ff4186 973 WCHAR szDir[MAX_PATH];
ansond 0:137634ff4186 974 char filename[MAX_PATH];
ansond 0:137634ff4186 975 char *p;
ansond 0:137634ff4186 976 int len = (int) strlen( path );
ansond 0:137634ff4186 977
ansond 0:137634ff4186 978 WIN32_FIND_DATAW file_data;
ansond 0:137634ff4186 979 HANDLE hFind;
ansond 0:137634ff4186 980
ansond 0:137634ff4186 981 if( len > MAX_PATH - 3 )
ansond 0:137634ff4186 982 return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
ansond 0:137634ff4186 983
ansond 0:137634ff4186 984 memset( szDir, 0, sizeof(szDir) );
ansond 0:137634ff4186 985 memset( filename, 0, MAX_PATH );
ansond 0:137634ff4186 986 memcpy( filename, path, len );
ansond 0:137634ff4186 987 filename[len++] = '\\';
ansond 0:137634ff4186 988 p = filename + len;
ansond 0:137634ff4186 989 filename[len++] = '*';
ansond 0:137634ff4186 990
ansond 0:137634ff4186 991 w_ret = MultiByteToWideChar( CP_ACP, 0, filename, len, szDir,
ansond 0:137634ff4186 992 MAX_PATH - 3 );
ansond 0:137634ff4186 993 if( w_ret == 0 )
ansond 0:137634ff4186 994 return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
ansond 0:137634ff4186 995
ansond 0:137634ff4186 996 hFind = FindFirstFileW( szDir, &file_data );
ansond 0:137634ff4186 997 if( hFind == INVALID_HANDLE_VALUE )
ansond 0:137634ff4186 998 return( POLARSSL_ERR_X509_FILE_IO_ERROR );
ansond 0:137634ff4186 999
ansond 0:137634ff4186 1000 len = MAX_PATH - len;
ansond 0:137634ff4186 1001 do
ansond 0:137634ff4186 1002 {
ansond 0:137634ff4186 1003 memset( p, 0, len );
ansond 0:137634ff4186 1004
ansond 0:137634ff4186 1005 if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
ansond 0:137634ff4186 1006 continue;
ansond 0:137634ff4186 1007
ansond 0:137634ff4186 1008 w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName,
ansond 0:137634ff4186 1009 lstrlenW( file_data.cFileName ),
ansond 0:137634ff4186 1010 p, len - 1,
ansond 0:137634ff4186 1011 NULL, NULL );
ansond 0:137634ff4186 1012 if( w_ret == 0 )
ansond 0:137634ff4186 1013 return( POLARSSL_ERR_X509_FILE_IO_ERROR );
ansond 0:137634ff4186 1014
ansond 0:137634ff4186 1015 w_ret = x509_crt_parse_file( chain, filename );
ansond 0:137634ff4186 1016 if( w_ret < 0 )
ansond 0:137634ff4186 1017 ret++;
ansond 0:137634ff4186 1018 else
ansond 0:137634ff4186 1019 ret += w_ret;
ansond 0:137634ff4186 1020 }
ansond 0:137634ff4186 1021 while( FindNextFileW( hFind, &file_data ) != 0 );
ansond 0:137634ff4186 1022
ansond 0:137634ff4186 1023 if( GetLastError() != ERROR_NO_MORE_FILES )
ansond 0:137634ff4186 1024 ret = POLARSSL_ERR_X509_FILE_IO_ERROR;
ansond 0:137634ff4186 1025
ansond 0:137634ff4186 1026 FindClose( hFind );
ansond 0:137634ff4186 1027 #else /* _WIN32 */
ansond 0:137634ff4186 1028 int t_ret;
ansond 0:137634ff4186 1029 struct stat sb;
ansond 0:137634ff4186 1030 struct dirent *entry;
ansond 0:137634ff4186 1031 char entry_name[255];
ansond 0:137634ff4186 1032 DIR *dir = opendir( path );
ansond 0:137634ff4186 1033
ansond 0:137634ff4186 1034 if( dir == NULL )
ansond 0:137634ff4186 1035 return( POLARSSL_ERR_X509_FILE_IO_ERROR );
ansond 0:137634ff4186 1036
ansond 0:137634ff4186 1037 #if defined(POLARSSL_THREADING_PTHREAD)
ansond 0:137634ff4186 1038 if( ( ret = polarssl_mutex_lock( &readdir_mutex ) ) != 0 )
ansond 0:137634ff4186 1039 return( ret );
ansond 0:137634ff4186 1040 #endif
ansond 0:137634ff4186 1041
ansond 0:137634ff4186 1042 while( ( entry = readdir( dir ) ) != NULL )
ansond 0:137634ff4186 1043 {
ansond 0:137634ff4186 1044 polarssl_snprintf( entry_name, sizeof entry_name, "%s/%s", path, entry->d_name );
ansond 0:137634ff4186 1045
ansond 0:137634ff4186 1046 if( stat( entry_name, &sb ) == -1 )
ansond 0:137634ff4186 1047 {
ansond 0:137634ff4186 1048 closedir( dir );
ansond 0:137634ff4186 1049 ret = POLARSSL_ERR_X509_FILE_IO_ERROR;
ansond 0:137634ff4186 1050 goto cleanup;
ansond 0:137634ff4186 1051 }
ansond 0:137634ff4186 1052
ansond 0:137634ff4186 1053 if( !S_ISREG( sb.st_mode ) )
ansond 0:137634ff4186 1054 continue;
ansond 0:137634ff4186 1055
ansond 0:137634ff4186 1056 // Ignore parse errors
ansond 0:137634ff4186 1057 //
ansond 0:137634ff4186 1058 t_ret = x509_crt_parse_file( chain, entry_name );
ansond 0:137634ff4186 1059 if( t_ret < 0 )
ansond 0:137634ff4186 1060 ret++;
ansond 0:137634ff4186 1061 else
ansond 0:137634ff4186 1062 ret += t_ret;
ansond 0:137634ff4186 1063 }
ansond 0:137634ff4186 1064 closedir( dir );
ansond 0:137634ff4186 1065
ansond 0:137634ff4186 1066 cleanup:
ansond 0:137634ff4186 1067 #if defined(POLARSSL_THREADING_PTHREAD)
ansond 0:137634ff4186 1068 if( polarssl_mutex_unlock( &readdir_mutex ) != 0 )
ansond 0:137634ff4186 1069 ret = POLARSSL_ERR_THREADING_MUTEX_ERROR;
ansond 0:137634ff4186 1070 #endif
ansond 0:137634ff4186 1071
ansond 0:137634ff4186 1072 #endif /* _WIN32 */
ansond 0:137634ff4186 1073
ansond 0:137634ff4186 1074 return( ret );
ansond 0:137634ff4186 1075 }
ansond 0:137634ff4186 1076 #endif /* POLARSSL_FS_IO */
ansond 0:137634ff4186 1077
ansond 0:137634ff4186 1078 #if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \
ansond 0:137634ff4186 1079 !defined(EFI32)
ansond 0:137634ff4186 1080 #include <stdarg.h>
ansond 0:137634ff4186 1081
ansond 0:137634ff4186 1082 #if !defined vsnprintf
ansond 0:137634ff4186 1083 #define vsnprintf _vsnprintf
ansond 0:137634ff4186 1084 #endif // vsnprintf
ansond 0:137634ff4186 1085
ansond 0:137634ff4186 1086 /*
ansond 0:137634ff4186 1087 * Windows _snprintf and _vsnprintf are not compatible to linux versions.
ansond 0:137634ff4186 1088 * Result value is not size of buffer needed, but -1 if no fit is possible.
ansond 0:137634ff4186 1089 *
ansond 0:137634ff4186 1090 * This fuction tries to 'fix' this by at least suggesting enlarging the
ansond 0:137634ff4186 1091 * size by 20.
ansond 0:137634ff4186 1092 */
ansond 0:137634ff4186 1093 static int compat_snprintf( char *str, size_t size, const char *format, ... )
ansond 0:137634ff4186 1094 {
ansond 0:137634ff4186 1095 va_list ap;
ansond 0:137634ff4186 1096 int res = -1;
ansond 0:137634ff4186 1097
ansond 0:137634ff4186 1098 va_start( ap, format );
ansond 0:137634ff4186 1099
ansond 0:137634ff4186 1100 res = vsnprintf( str, size, format, ap );
ansond 0:137634ff4186 1101
ansond 0:137634ff4186 1102 va_end( ap );
ansond 0:137634ff4186 1103
ansond 0:137634ff4186 1104 // No quick fix possible
ansond 0:137634ff4186 1105 if( res < 0 )
ansond 0:137634ff4186 1106 return( (int) size + 20 );
ansond 0:137634ff4186 1107
ansond 0:137634ff4186 1108 return( res );
ansond 0:137634ff4186 1109 }
ansond 0:137634ff4186 1110
ansond 0:137634ff4186 1111 #define snprintf compat_snprintf
ansond 0:137634ff4186 1112 #endif /* _MSC_VER && !snprintf && !EFIX64 && !EFI32 */
ansond 0:137634ff4186 1113
ansond 0:137634ff4186 1114 #define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL -2
ansond 0:137634ff4186 1115
ansond 0:137634ff4186 1116 #define SAFE_SNPRINTF() \
ansond 0:137634ff4186 1117 { \
ansond 0:137634ff4186 1118 if( ret == -1 ) \
ansond 0:137634ff4186 1119 return( -1 ); \
ansond 0:137634ff4186 1120 \
ansond 0:137634ff4186 1121 if( (unsigned int) ret > n ) { \
ansond 0:137634ff4186 1122 p[n - 1] = '\0'; \
ansond 0:137634ff4186 1123 return( POLARSSL_ERR_DEBUG_BUF_TOO_SMALL ); \
ansond 0:137634ff4186 1124 } \
ansond 0:137634ff4186 1125 \
ansond 0:137634ff4186 1126 n -= (unsigned int) ret; \
ansond 0:137634ff4186 1127 p += (unsigned int) ret; \
ansond 0:137634ff4186 1128 }
ansond 0:137634ff4186 1129
ansond 0:137634ff4186 1130 static int x509_info_subject_alt_name( char **buf, size_t *size,
ansond 0:137634ff4186 1131 const x509_sequence *subject_alt_name )
ansond 0:137634ff4186 1132 {
ansond 0:137634ff4186 1133 size_t i;
ansond 0:137634ff4186 1134 size_t n = *size;
ansond 0:137634ff4186 1135 char *p = *buf;
ansond 0:137634ff4186 1136 const x509_sequence *cur = subject_alt_name;
ansond 0:137634ff4186 1137 const char *sep = "";
ansond 0:137634ff4186 1138 size_t sep_len = 0;
ansond 0:137634ff4186 1139
ansond 0:137634ff4186 1140 while( cur != NULL )
ansond 0:137634ff4186 1141 {
ansond 0:137634ff4186 1142 if( cur->buf.len + sep_len >= n )
ansond 0:137634ff4186 1143 {
ansond 0:137634ff4186 1144 *p = '\0';
ansond 0:137634ff4186 1145 return( POLARSSL_ERR_DEBUG_BUF_TOO_SMALL );
ansond 0:137634ff4186 1146 }
ansond 0:137634ff4186 1147
ansond 0:137634ff4186 1148 n -= cur->buf.len + sep_len;
ansond 0:137634ff4186 1149 for( i = 0; i < sep_len; i++ )
ansond 0:137634ff4186 1150 *p++ = sep[i];
ansond 0:137634ff4186 1151 for( i = 0; i < cur->buf.len; i++ )
ansond 0:137634ff4186 1152 *p++ = cur->buf.p[i];
ansond 0:137634ff4186 1153
ansond 0:137634ff4186 1154 sep = ", ";
ansond 0:137634ff4186 1155 sep_len = 2;
ansond 0:137634ff4186 1156
ansond 0:137634ff4186 1157 cur = cur->next;
ansond 0:137634ff4186 1158 }
ansond 0:137634ff4186 1159
ansond 0:137634ff4186 1160 *p = '\0';
ansond 0:137634ff4186 1161
ansond 0:137634ff4186 1162 *size = n;
ansond 0:137634ff4186 1163 *buf = p;
ansond 0:137634ff4186 1164
ansond 0:137634ff4186 1165 return( 0 );
ansond 0:137634ff4186 1166 }
ansond 0:137634ff4186 1167
ansond 0:137634ff4186 1168 #define PRINT_ITEM(i) \
ansond 0:137634ff4186 1169 { \
ansond 0:137634ff4186 1170 ret = polarssl_snprintf( p, n, "%s" i, sep ); \
ansond 0:137634ff4186 1171 SAFE_SNPRINTF(); \
ansond 0:137634ff4186 1172 sep = ", "; \
ansond 0:137634ff4186 1173 }
ansond 0:137634ff4186 1174
ansond 0:137634ff4186 1175 #define CERT_TYPE(type,name) \
ansond 0:137634ff4186 1176 if( ns_cert_type & type ) \
ansond 0:137634ff4186 1177 PRINT_ITEM( name );
ansond 0:137634ff4186 1178
ansond 0:137634ff4186 1179 static int x509_info_cert_type( char **buf, size_t *size,
ansond 0:137634ff4186 1180 unsigned char ns_cert_type )
ansond 0:137634ff4186 1181 {
ansond 0:137634ff4186 1182 int ret;
ansond 0:137634ff4186 1183 size_t n = *size;
ansond 0:137634ff4186 1184 char *p = *buf;
ansond 0:137634ff4186 1185 const char *sep = "";
ansond 0:137634ff4186 1186
ansond 0:137634ff4186 1187 CERT_TYPE( NS_CERT_TYPE_SSL_CLIENT, "SSL Client" );
ansond 0:137634ff4186 1188 CERT_TYPE( NS_CERT_TYPE_SSL_SERVER, "SSL Server" );
ansond 0:137634ff4186 1189 CERT_TYPE( NS_CERT_TYPE_EMAIL, "Email" );
ansond 0:137634ff4186 1190 CERT_TYPE( NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing" );
ansond 0:137634ff4186 1191 CERT_TYPE( NS_CERT_TYPE_RESERVED, "Reserved" );
ansond 0:137634ff4186 1192 CERT_TYPE( NS_CERT_TYPE_SSL_CA, "SSL CA" );
ansond 0:137634ff4186 1193 CERT_TYPE( NS_CERT_TYPE_EMAIL_CA, "Email CA" );
ansond 0:137634ff4186 1194 CERT_TYPE( NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA" );
ansond 0:137634ff4186 1195
ansond 0:137634ff4186 1196 *size = n;
ansond 0:137634ff4186 1197 *buf = p;
ansond 0:137634ff4186 1198
ansond 0:137634ff4186 1199 return( 0 );
ansond 0:137634ff4186 1200 }
ansond 0:137634ff4186 1201
ansond 0:137634ff4186 1202 #define KEY_USAGE(code,name) \
ansond 0:137634ff4186 1203 if( key_usage & code ) \
ansond 0:137634ff4186 1204 PRINT_ITEM( name );
ansond 0:137634ff4186 1205
ansond 0:137634ff4186 1206 static int x509_info_key_usage( char **buf, size_t *size,
ansond 0:137634ff4186 1207 unsigned char key_usage )
ansond 0:137634ff4186 1208 {
ansond 0:137634ff4186 1209 int ret;
ansond 0:137634ff4186 1210 size_t n = *size;
ansond 0:137634ff4186 1211 char *p = *buf;
ansond 0:137634ff4186 1212 const char *sep = "";
ansond 0:137634ff4186 1213
ansond 0:137634ff4186 1214 KEY_USAGE( KU_DIGITAL_SIGNATURE, "Digital Signature" );
ansond 0:137634ff4186 1215 KEY_USAGE( KU_NON_REPUDIATION, "Non Repudiation" );
ansond 0:137634ff4186 1216 KEY_USAGE( KU_KEY_ENCIPHERMENT, "Key Encipherment" );
ansond 0:137634ff4186 1217 KEY_USAGE( KU_DATA_ENCIPHERMENT, "Data Encipherment" );
ansond 0:137634ff4186 1218 KEY_USAGE( KU_KEY_AGREEMENT, "Key Agreement" );
ansond 0:137634ff4186 1219 KEY_USAGE( KU_KEY_CERT_SIGN, "Key Cert Sign" );
ansond 0:137634ff4186 1220 KEY_USAGE( KU_CRL_SIGN, "CRL Sign" );
ansond 0:137634ff4186 1221
ansond 0:137634ff4186 1222 *size = n;
ansond 0:137634ff4186 1223 *buf = p;
ansond 0:137634ff4186 1224
ansond 0:137634ff4186 1225 return( 0 );
ansond 0:137634ff4186 1226 }
ansond 0:137634ff4186 1227
ansond 0:137634ff4186 1228 static int x509_info_ext_key_usage( char **buf, size_t *size,
ansond 0:137634ff4186 1229 const x509_sequence *extended_key_usage )
ansond 0:137634ff4186 1230 {
ansond 0:137634ff4186 1231 int ret;
ansond 0:137634ff4186 1232 const char *desc;
ansond 0:137634ff4186 1233 size_t n = *size;
ansond 0:137634ff4186 1234 char *p = *buf;
ansond 0:137634ff4186 1235 const x509_sequence *cur = extended_key_usage;
ansond 0:137634ff4186 1236 const char *sep = "";
ansond 0:137634ff4186 1237
ansond 0:137634ff4186 1238 while( cur != NULL )
ansond 0:137634ff4186 1239 {
ansond 0:137634ff4186 1240 if( oid_get_extended_key_usage( &cur->buf, &desc ) != 0 )
ansond 0:137634ff4186 1241 desc = "???";
ansond 0:137634ff4186 1242
ansond 0:137634ff4186 1243 ret = polarssl_snprintf( p, n, "%s%s", sep, desc );
ansond 0:137634ff4186 1244 SAFE_SNPRINTF();
ansond 0:137634ff4186 1245
ansond 0:137634ff4186 1246 sep = ", ";
ansond 0:137634ff4186 1247
ansond 0:137634ff4186 1248 cur = cur->next;
ansond 0:137634ff4186 1249 }
ansond 0:137634ff4186 1250
ansond 0:137634ff4186 1251 *size = n;
ansond 0:137634ff4186 1252 *buf = p;
ansond 0:137634ff4186 1253
ansond 0:137634ff4186 1254 return( 0 );
ansond 0:137634ff4186 1255 }
ansond 0:137634ff4186 1256
ansond 0:137634ff4186 1257 /*
ansond 0:137634ff4186 1258 * Return an informational string about the certificate.
ansond 0:137634ff4186 1259 */
ansond 0:137634ff4186 1260 #define BEFORE_COLON 18
ansond 0:137634ff4186 1261 #define BC "18"
ansond 0:137634ff4186 1262 int x509_crt_info( char *buf, size_t size, const char *prefix,
ansond 0:137634ff4186 1263 const x509_crt *crt )
ansond 0:137634ff4186 1264 {
ansond 0:137634ff4186 1265 int ret;
ansond 0:137634ff4186 1266 size_t n;
ansond 0:137634ff4186 1267 char *p;
ansond 0:137634ff4186 1268 char key_size_str[BEFORE_COLON];
ansond 0:137634ff4186 1269
ansond 0:137634ff4186 1270 p = buf;
ansond 0:137634ff4186 1271 n = size;
ansond 0:137634ff4186 1272
ansond 0:137634ff4186 1273 ret = polarssl_snprintf( p, n, "%scert. version : %d\n",
ansond 0:137634ff4186 1274 prefix, crt->version );
ansond 0:137634ff4186 1275 SAFE_SNPRINTF();
ansond 0:137634ff4186 1276 ret = polarssl_snprintf( p, n, "%sserial number : ",
ansond 0:137634ff4186 1277 prefix );
ansond 0:137634ff4186 1278 SAFE_SNPRINTF();
ansond 0:137634ff4186 1279
ansond 0:137634ff4186 1280 ret = x509_serial_gets( p, n, &crt->serial );
ansond 0:137634ff4186 1281 SAFE_SNPRINTF();
ansond 0:137634ff4186 1282
ansond 0:137634ff4186 1283 ret = polarssl_snprintf( p, n, "\n%sissuer name : ", prefix );
ansond 0:137634ff4186 1284 SAFE_SNPRINTF();
ansond 0:137634ff4186 1285 ret = x509_dn_gets( p, n, &crt->issuer );
ansond 0:137634ff4186 1286 SAFE_SNPRINTF();
ansond 0:137634ff4186 1287
ansond 0:137634ff4186 1288 ret = polarssl_snprintf( p, n, "\n%ssubject name : ", prefix );
ansond 0:137634ff4186 1289 SAFE_SNPRINTF();
ansond 0:137634ff4186 1290 ret = x509_dn_gets( p, n, &crt->subject );
ansond 0:137634ff4186 1291 SAFE_SNPRINTF();
ansond 0:137634ff4186 1292
ansond 0:137634ff4186 1293 ret = polarssl_snprintf( p, n, "\n%sissued on : " \
ansond 0:137634ff4186 1294 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
ansond 0:137634ff4186 1295 crt->valid_from.year, crt->valid_from.mon,
ansond 0:137634ff4186 1296 crt->valid_from.day, crt->valid_from.hour,
ansond 0:137634ff4186 1297 crt->valid_from.min, crt->valid_from.sec );
ansond 0:137634ff4186 1298 SAFE_SNPRINTF();
ansond 0:137634ff4186 1299
ansond 0:137634ff4186 1300 ret = polarssl_snprintf( p, n, "\n%sexpires on : " \
ansond 0:137634ff4186 1301 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
ansond 0:137634ff4186 1302 crt->valid_to.year, crt->valid_to.mon,
ansond 0:137634ff4186 1303 crt->valid_to.day, crt->valid_to.hour,
ansond 0:137634ff4186 1304 crt->valid_to.min, crt->valid_to.sec );
ansond 0:137634ff4186 1305 SAFE_SNPRINTF();
ansond 0:137634ff4186 1306
ansond 0:137634ff4186 1307 ret = polarssl_snprintf( p, n, "\n%ssigned using : ", prefix );
ansond 0:137634ff4186 1308 SAFE_SNPRINTF();
ansond 0:137634ff4186 1309
ansond 0:137634ff4186 1310 ret = x509_sig_alg_gets( p, n, &crt->sig_oid1, crt->sig_pk,
ansond 0:137634ff4186 1311 crt->sig_md, crt->sig_opts );
ansond 0:137634ff4186 1312 SAFE_SNPRINTF();
ansond 0:137634ff4186 1313
ansond 0:137634ff4186 1314 /* Key size */
ansond 0:137634ff4186 1315 if( ( ret = x509_key_size_helper( key_size_str, BEFORE_COLON,
ansond 0:137634ff4186 1316 pk_get_name( &crt->pk ) ) ) != 0 )
ansond 0:137634ff4186 1317 {
ansond 0:137634ff4186 1318 return( ret );
ansond 0:137634ff4186 1319 }
ansond 0:137634ff4186 1320
ansond 0:137634ff4186 1321 ret = polarssl_snprintf( p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str,
ansond 0:137634ff4186 1322 (int) pk_get_size( &crt->pk ) );
ansond 0:137634ff4186 1323 SAFE_SNPRINTF();
ansond 0:137634ff4186 1324
ansond 0:137634ff4186 1325 /*
ansond 0:137634ff4186 1326 * Optional extensions
ansond 0:137634ff4186 1327 */
ansond 0:137634ff4186 1328
ansond 0:137634ff4186 1329 if( crt->ext_types & EXT_BASIC_CONSTRAINTS )
ansond 0:137634ff4186 1330 {
ansond 0:137634ff4186 1331 ret = polarssl_snprintf( p, n, "\n%sbasic constraints : CA=%s", prefix,
ansond 0:137634ff4186 1332 crt->ca_istrue ? "true" : "false" );
ansond 0:137634ff4186 1333 SAFE_SNPRINTF();
ansond 0:137634ff4186 1334
ansond 0:137634ff4186 1335 if( crt->max_pathlen > 0 )
ansond 0:137634ff4186 1336 {
ansond 0:137634ff4186 1337 ret = polarssl_snprintf( p, n, ", max_pathlen=%d", crt->max_pathlen - 1 );
ansond 0:137634ff4186 1338 SAFE_SNPRINTF();
ansond 0:137634ff4186 1339 }
ansond 0:137634ff4186 1340 }
ansond 0:137634ff4186 1341
ansond 0:137634ff4186 1342 if( crt->ext_types & EXT_SUBJECT_ALT_NAME )
ansond 0:137634ff4186 1343 {
ansond 0:137634ff4186 1344 ret = polarssl_snprintf( p, n, "\n%ssubject alt name : ", prefix );
ansond 0:137634ff4186 1345 SAFE_SNPRINTF();
ansond 0:137634ff4186 1346
ansond 0:137634ff4186 1347 if( ( ret = x509_info_subject_alt_name( &p, &n,
ansond 0:137634ff4186 1348 &crt->subject_alt_names ) ) != 0 )
ansond 0:137634ff4186 1349 return( ret );
ansond 0:137634ff4186 1350 }
ansond 0:137634ff4186 1351
ansond 0:137634ff4186 1352 if( crt->ext_types & EXT_NS_CERT_TYPE )
ansond 0:137634ff4186 1353 {
ansond 0:137634ff4186 1354 ret = polarssl_snprintf( p, n, "\n%scert. type : ", prefix );
ansond 0:137634ff4186 1355 SAFE_SNPRINTF();
ansond 0:137634ff4186 1356
ansond 0:137634ff4186 1357 if( ( ret = x509_info_cert_type( &p, &n, crt->ns_cert_type ) ) != 0 )
ansond 0:137634ff4186 1358 return( ret );
ansond 0:137634ff4186 1359 }
ansond 0:137634ff4186 1360
ansond 0:137634ff4186 1361 if( crt->ext_types & EXT_KEY_USAGE )
ansond 0:137634ff4186 1362 {
ansond 0:137634ff4186 1363 ret = polarssl_snprintf( p, n, "\n%skey usage : ", prefix );
ansond 0:137634ff4186 1364 SAFE_SNPRINTF();
ansond 0:137634ff4186 1365
ansond 0:137634ff4186 1366 if( ( ret = x509_info_key_usage( &p, &n, crt->key_usage ) ) != 0 )
ansond 0:137634ff4186 1367 return( ret );
ansond 0:137634ff4186 1368 }
ansond 0:137634ff4186 1369
ansond 0:137634ff4186 1370 if( crt->ext_types & EXT_EXTENDED_KEY_USAGE )
ansond 0:137634ff4186 1371 {
ansond 0:137634ff4186 1372 ret = polarssl_snprintf( p, n, "\n%sext key usage : ", prefix );
ansond 0:137634ff4186 1373 SAFE_SNPRINTF();
ansond 0:137634ff4186 1374
ansond 0:137634ff4186 1375 if( ( ret = x509_info_ext_key_usage( &p, &n,
ansond 0:137634ff4186 1376 &crt->ext_key_usage ) ) != 0 )
ansond 0:137634ff4186 1377 return( ret );
ansond 0:137634ff4186 1378 }
ansond 0:137634ff4186 1379
ansond 0:137634ff4186 1380 ret = polarssl_snprintf( p, n, "\n" );
ansond 0:137634ff4186 1381 SAFE_SNPRINTF();
ansond 0:137634ff4186 1382
ansond 0:137634ff4186 1383 return( (int) ( size - n ) );
ansond 0:137634ff4186 1384 }
ansond 0:137634ff4186 1385
ansond 0:137634ff4186 1386 struct x509_crt_verify_string {
ansond 0:137634ff4186 1387 int code;
ansond 0:137634ff4186 1388 const char *string;
ansond 0:137634ff4186 1389 };
ansond 0:137634ff4186 1390
ansond 0:137634ff4186 1391 static const struct x509_crt_verify_string x509_crt_verify_strings[] = {
ansond 0:137634ff4186 1392 { BADCERT_EXPIRED, "The certificate validity has expired" },
ansond 0:137634ff4186 1393 { BADCERT_REVOKED, "The certificate has been revoked (is on a CRL)" },
ansond 0:137634ff4186 1394 { BADCERT_CN_MISMATCH, "The certificate Common Name (CN) does not match with the expected CN" },
ansond 0:137634ff4186 1395 { BADCERT_NOT_TRUSTED, "The certificate is not correctly signed by the trusted CA" },
ansond 0:137634ff4186 1396 { BADCRL_NOT_TRUSTED, "The CRL is not correctly signed by the trusted CA" },
ansond 0:137634ff4186 1397 { BADCRL_EXPIRED, "The CRL is expired" },
ansond 0:137634ff4186 1398 { BADCERT_MISSING, "Certificate was missing" },
ansond 0:137634ff4186 1399 { BADCERT_SKIP_VERIFY, "Certificate verification was skipped" },
ansond 0:137634ff4186 1400 { BADCERT_OTHER, "Other reason (can be used by verify callback)" },
ansond 0:137634ff4186 1401 { BADCERT_FUTURE, "The certificate validity starts in the future" },
ansond 0:137634ff4186 1402 { BADCRL_FUTURE, "The CRL is from the future" },
ansond 0:137634ff4186 1403 { BADCERT_KEY_USAGE, "Usage does not match the keyUsage extension" },
ansond 0:137634ff4186 1404 { BADCERT_EXT_KEY_USAGE, "Usage does not match the extendedKeyUsage extension" },
ansond 0:137634ff4186 1405 { BADCERT_NS_CERT_TYPE, "Usage does not match the nsCertType extension" },
ansond 0:137634ff4186 1406 { 0, NULL }
ansond 0:137634ff4186 1407 };
ansond 0:137634ff4186 1408
ansond 0:137634ff4186 1409 int x509_crt_verify_info( char *buf, size_t size, const char *prefix,
ansond 0:137634ff4186 1410 int flags )
ansond 0:137634ff4186 1411 {
ansond 0:137634ff4186 1412 int ret;
ansond 0:137634ff4186 1413 const struct x509_crt_verify_string *cur;
ansond 0:137634ff4186 1414 char *p = buf;
ansond 0:137634ff4186 1415 size_t n = size;
ansond 0:137634ff4186 1416
ansond 0:137634ff4186 1417 for( cur = x509_crt_verify_strings; cur->string != NULL ; cur++ )
ansond 0:137634ff4186 1418 {
ansond 0:137634ff4186 1419 if( ( flags & cur->code ) == 0 )
ansond 0:137634ff4186 1420 continue;
ansond 0:137634ff4186 1421
ansond 0:137634ff4186 1422 ret = polarssl_snprintf( p, n, "%s%s\n", prefix, cur->string );
ansond 0:137634ff4186 1423 SAFE_SNPRINTF();
ansond 0:137634ff4186 1424 flags ^= cur->code;
ansond 0:137634ff4186 1425 }
ansond 0:137634ff4186 1426
ansond 0:137634ff4186 1427 if( flags != 0 )
ansond 0:137634ff4186 1428 {
ansond 0:137634ff4186 1429 ret = polarssl_snprintf( p, n, "%sUnknown reason "
ansond 0:137634ff4186 1430 "(this should not happen)\n", prefix );
ansond 0:137634ff4186 1431 SAFE_SNPRINTF();
ansond 0:137634ff4186 1432 }
ansond 0:137634ff4186 1433
ansond 0:137634ff4186 1434 return( (int) ( size - n ) );
ansond 0:137634ff4186 1435 }
ansond 0:137634ff4186 1436
ansond 0:137634ff4186 1437 #if defined(POLARSSL_X509_CHECK_KEY_USAGE)
ansond 0:137634ff4186 1438 int x509_crt_check_key_usage( const x509_crt *crt, int usage )
ansond 0:137634ff4186 1439 {
ansond 0:137634ff4186 1440 if( ( crt->ext_types & EXT_KEY_USAGE ) != 0 &&
ansond 0:137634ff4186 1441 ( crt->key_usage & usage ) != usage )
ansond 0:137634ff4186 1442 return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
ansond 0:137634ff4186 1443
ansond 0:137634ff4186 1444 return( 0 );
ansond 0:137634ff4186 1445 }
ansond 0:137634ff4186 1446 #endif
ansond 0:137634ff4186 1447
ansond 0:137634ff4186 1448 #if defined(POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE)
ansond 0:137634ff4186 1449 int x509_crt_check_extended_key_usage( const x509_crt *crt,
ansond 0:137634ff4186 1450 const char *usage_oid,
ansond 0:137634ff4186 1451 size_t usage_len )
ansond 0:137634ff4186 1452 {
ansond 0:137634ff4186 1453 const x509_sequence *cur;
ansond 0:137634ff4186 1454
ansond 0:137634ff4186 1455 /* Extension is not mandatory, absent means no restriction */
ansond 0:137634ff4186 1456 if( ( crt->ext_types & EXT_EXTENDED_KEY_USAGE ) == 0 )
ansond 0:137634ff4186 1457 return( 0 );
ansond 0:137634ff4186 1458
ansond 0:137634ff4186 1459 /*
ansond 0:137634ff4186 1460 * Look for the requested usage (or wildcard ANY) in our list
ansond 0:137634ff4186 1461 */
ansond 0:137634ff4186 1462 for( cur = &crt->ext_key_usage; cur != NULL; cur = cur->next )
ansond 0:137634ff4186 1463 {
ansond 0:137634ff4186 1464 const x509_buf *cur_oid = &cur->buf;
ansond 0:137634ff4186 1465
ansond 0:137634ff4186 1466 if( cur_oid->len == usage_len &&
ansond 0:137634ff4186 1467 memcmp( cur_oid->p, usage_oid, usage_len ) == 0 )
ansond 0:137634ff4186 1468 {
ansond 0:137634ff4186 1469 return( 0 );
ansond 0:137634ff4186 1470 }
ansond 0:137634ff4186 1471
ansond 0:137634ff4186 1472 if( OID_CMP( OID_ANY_EXTENDED_KEY_USAGE, cur_oid ) )
ansond 0:137634ff4186 1473 return( 0 );
ansond 0:137634ff4186 1474 }
ansond 0:137634ff4186 1475
ansond 0:137634ff4186 1476 return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
ansond 0:137634ff4186 1477 }
ansond 0:137634ff4186 1478 #endif /* POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE */
ansond 0:137634ff4186 1479
ansond 0:137634ff4186 1480 #if defined(POLARSSL_X509_CRL_PARSE_C)
ansond 0:137634ff4186 1481 /*
ansond 0:137634ff4186 1482 * Return 1 if the certificate is revoked, or 0 otherwise.
ansond 0:137634ff4186 1483 */
ansond 0:137634ff4186 1484 int x509_crt_revoked( const x509_crt *crt, const x509_crl *crl )
ansond 0:137634ff4186 1485 {
ansond 0:137634ff4186 1486 const x509_crl_entry *cur = &crl->entry;
ansond 0:137634ff4186 1487
ansond 0:137634ff4186 1488 while( cur != NULL && cur->serial.len != 0 )
ansond 0:137634ff4186 1489 {
ansond 0:137634ff4186 1490 if( crt->serial.len == cur->serial.len &&
ansond 0:137634ff4186 1491 memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 )
ansond 0:137634ff4186 1492 {
ansond 0:137634ff4186 1493 if( x509_time_expired( &cur->revocation_date ) )
ansond 0:137634ff4186 1494 return( 1 );
ansond 0:137634ff4186 1495 }
ansond 0:137634ff4186 1496
ansond 0:137634ff4186 1497 cur = cur->next;
ansond 0:137634ff4186 1498 }
ansond 0:137634ff4186 1499
ansond 0:137634ff4186 1500 return( 0 );
ansond 0:137634ff4186 1501 }
ansond 0:137634ff4186 1502
ansond 0:137634ff4186 1503 /*
ansond 0:137634ff4186 1504 * Check that the given certificate is valid according to the CRL.
ansond 0:137634ff4186 1505 */
ansond 0:137634ff4186 1506 static int x509_crt_verifycrl( x509_crt *crt, x509_crt *ca,
ansond 0:137634ff4186 1507 x509_crl *crl_list)
ansond 0:137634ff4186 1508 {
ansond 0:137634ff4186 1509 int flags = 0;
ansond 0:137634ff4186 1510 unsigned char hash[POLARSSL_MD_MAX_SIZE];
ansond 0:137634ff4186 1511 const md_info_t *md_info;
ansond 0:137634ff4186 1512
ansond 0:137634ff4186 1513 if( ca == NULL )
ansond 0:137634ff4186 1514 return( flags );
ansond 0:137634ff4186 1515
ansond 0:137634ff4186 1516 /*
ansond 0:137634ff4186 1517 * TODO: What happens if no CRL is present?
ansond 0:137634ff4186 1518 * Suggestion: Revocation state should be unknown if no CRL is present.
ansond 0:137634ff4186 1519 * For backwards compatibility this is not yet implemented.
ansond 0:137634ff4186 1520 */
ansond 0:137634ff4186 1521
ansond 0:137634ff4186 1522 while( crl_list != NULL )
ansond 0:137634ff4186 1523 {
ansond 0:137634ff4186 1524 if( crl_list->version == 0 ||
ansond 0:137634ff4186 1525 crl_list->issuer_raw.len != ca->subject_raw.len ||
ansond 0:137634ff4186 1526 memcmp( crl_list->issuer_raw.p, ca->subject_raw.p,
ansond 0:137634ff4186 1527 crl_list->issuer_raw.len ) != 0 )
ansond 0:137634ff4186 1528 {
ansond 0:137634ff4186 1529 crl_list = crl_list->next;
ansond 0:137634ff4186 1530 continue;
ansond 0:137634ff4186 1531 }
ansond 0:137634ff4186 1532
ansond 0:137634ff4186 1533 /*
ansond 0:137634ff4186 1534 * Check if the CA is configured to sign CRLs
ansond 0:137634ff4186 1535 */
ansond 0:137634ff4186 1536 #if defined(POLARSSL_X509_CHECK_KEY_USAGE)
ansond 0:137634ff4186 1537 if( x509_crt_check_key_usage( ca, KU_CRL_SIGN ) != 0 )
ansond 0:137634ff4186 1538 {
ansond 0:137634ff4186 1539 flags |= BADCRL_NOT_TRUSTED;
ansond 0:137634ff4186 1540 break;
ansond 0:137634ff4186 1541 }
ansond 0:137634ff4186 1542 #endif
ansond 0:137634ff4186 1543
ansond 0:137634ff4186 1544 /*
ansond 0:137634ff4186 1545 * Check if CRL is correctly signed by the trusted CA
ansond 0:137634ff4186 1546 */
ansond 0:137634ff4186 1547 md_info = md_info_from_type( crl_list->sig_md );
ansond 0:137634ff4186 1548 if( md_info == NULL )
ansond 0:137634ff4186 1549 {
ansond 0:137634ff4186 1550 /*
ansond 0:137634ff4186 1551 * Cannot check 'unknown' hash
ansond 0:137634ff4186 1552 */
ansond 0:137634ff4186 1553 flags |= BADCRL_NOT_TRUSTED;
ansond 0:137634ff4186 1554 break;
ansond 0:137634ff4186 1555 }
ansond 0:137634ff4186 1556
ansond 0:137634ff4186 1557 md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash );
ansond 0:137634ff4186 1558
ansond 0:137634ff4186 1559 if( pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, &ca->pk,
ansond 0:137634ff4186 1560 crl_list->sig_md, hash, md_info->size,
ansond 0:137634ff4186 1561 crl_list->sig.p, crl_list->sig.len ) != 0 )
ansond 0:137634ff4186 1562 {
ansond 0:137634ff4186 1563 flags |= BADCRL_NOT_TRUSTED;
ansond 0:137634ff4186 1564 break;
ansond 0:137634ff4186 1565 }
ansond 0:137634ff4186 1566
ansond 0:137634ff4186 1567 /*
ansond 0:137634ff4186 1568 * Check for validity of CRL (Do not drop out)
ansond 0:137634ff4186 1569 */
ansond 0:137634ff4186 1570 if( x509_time_expired( &crl_list->next_update ) )
ansond 0:137634ff4186 1571 flags |= BADCRL_EXPIRED;
ansond 0:137634ff4186 1572
ansond 0:137634ff4186 1573 if( x509_time_future( &crl_list->this_update ) )
ansond 0:137634ff4186 1574 flags |= BADCRL_FUTURE;
ansond 0:137634ff4186 1575
ansond 0:137634ff4186 1576 /*
ansond 0:137634ff4186 1577 * Check if certificate is revoked
ansond 0:137634ff4186 1578 */
ansond 0:137634ff4186 1579 if( x509_crt_revoked( crt, crl_list ) )
ansond 0:137634ff4186 1580 {
ansond 0:137634ff4186 1581 flags |= BADCERT_REVOKED;
ansond 0:137634ff4186 1582 break;
ansond 0:137634ff4186 1583 }
ansond 0:137634ff4186 1584
ansond 0:137634ff4186 1585 crl_list = crl_list->next;
ansond 0:137634ff4186 1586 }
ansond 0:137634ff4186 1587 return( flags );
ansond 0:137634ff4186 1588 }
ansond 0:137634ff4186 1589 #endif /* POLARSSL_X509_CRL_PARSE_C */
ansond 0:137634ff4186 1590
ansond 0:137634ff4186 1591 /*
ansond 0:137634ff4186 1592 * Like memcmp, but case-insensitive and always returns -1 if different
ansond 0:137634ff4186 1593 */
ansond 0:137634ff4186 1594 static int x509_memcasecmp( const void *s1, const void *s2, size_t len )
ansond 0:137634ff4186 1595 {
ansond 0:137634ff4186 1596 size_t i;
ansond 0:137634ff4186 1597 unsigned char diff;
ansond 0:137634ff4186 1598 const unsigned char *n1 = s1, *n2 = s2;
ansond 0:137634ff4186 1599
ansond 0:137634ff4186 1600 for( i = 0; i < len; i++ )
ansond 0:137634ff4186 1601 {
ansond 0:137634ff4186 1602 diff = n1[i] ^ n2[i];
ansond 0:137634ff4186 1603
ansond 0:137634ff4186 1604 if( diff == 0 )
ansond 0:137634ff4186 1605 continue;
ansond 0:137634ff4186 1606
ansond 0:137634ff4186 1607 if( diff == 32 &&
ansond 0:137634ff4186 1608 ( ( n1[i] >= 'a' && n1[i] <= 'z' ) ||
ansond 0:137634ff4186 1609 ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) )
ansond 0:137634ff4186 1610 {
ansond 0:137634ff4186 1611 continue;
ansond 0:137634ff4186 1612 }
ansond 0:137634ff4186 1613
ansond 0:137634ff4186 1614 return( -1 );
ansond 0:137634ff4186 1615 }
ansond 0:137634ff4186 1616
ansond 0:137634ff4186 1617 return( 0 );
ansond 0:137634ff4186 1618 }
ansond 0:137634ff4186 1619
ansond 0:137634ff4186 1620 /*
ansond 0:137634ff4186 1621 * Return 1 if match, 0 if not
ansond 0:137634ff4186 1622 * TODO: inverted return value!
ansond 0:137634ff4186 1623 */
ansond 0:137634ff4186 1624 static int x509_wildcard_verify( const char *cn, x509_buf *name )
ansond 0:137634ff4186 1625 {
ansond 0:137634ff4186 1626 size_t i;
ansond 0:137634ff4186 1627 size_t cn_idx = 0, cn_len = strlen( cn );
ansond 0:137634ff4186 1628
ansond 0:137634ff4186 1629 if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' )
ansond 0:137634ff4186 1630 return( 0 );
ansond 0:137634ff4186 1631
ansond 0:137634ff4186 1632 for( i = 0; i < cn_len; ++i )
ansond 0:137634ff4186 1633 {
ansond 0:137634ff4186 1634 if( cn[i] == '.' )
ansond 0:137634ff4186 1635 {
ansond 0:137634ff4186 1636 cn_idx = i;
ansond 0:137634ff4186 1637 break;
ansond 0:137634ff4186 1638 }
ansond 0:137634ff4186 1639 }
ansond 0:137634ff4186 1640
ansond 0:137634ff4186 1641 if( cn_idx == 0 )
ansond 0:137634ff4186 1642 return( 0 );
ansond 0:137634ff4186 1643
ansond 0:137634ff4186 1644 if( cn_len - cn_idx == name->len - 1 &&
ansond 0:137634ff4186 1645 x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 )
ansond 0:137634ff4186 1646 {
ansond 0:137634ff4186 1647 return( 1 );
ansond 0:137634ff4186 1648 }
ansond 0:137634ff4186 1649
ansond 0:137634ff4186 1650 return( 0 );
ansond 0:137634ff4186 1651 }
ansond 0:137634ff4186 1652
ansond 0:137634ff4186 1653 /*
ansond 0:137634ff4186 1654 * Compare two X.509 strings, case-insensitive, and allowing for some encoding
ansond 0:137634ff4186 1655 * variations (but not all).
ansond 0:137634ff4186 1656 *
ansond 0:137634ff4186 1657 * Return 0 if equal, -1 otherwise.
ansond 0:137634ff4186 1658 */
ansond 0:137634ff4186 1659 static int x509_string_cmp( const x509_buf *a, const x509_buf *b )
ansond 0:137634ff4186 1660 {
ansond 0:137634ff4186 1661 if( a->tag == b->tag &&
ansond 0:137634ff4186 1662 a->len == b->len &&
ansond 0:137634ff4186 1663 memcmp( a->p, b->p, b->len ) == 0 )
ansond 0:137634ff4186 1664 {
ansond 0:137634ff4186 1665 return( 0 );
ansond 0:137634ff4186 1666 }
ansond 0:137634ff4186 1667
ansond 0:137634ff4186 1668 if( ( a->tag == ASN1_UTF8_STRING || a->tag == ASN1_PRINTABLE_STRING ) &&
ansond 0:137634ff4186 1669 ( b->tag == ASN1_UTF8_STRING || b->tag == ASN1_PRINTABLE_STRING ) &&
ansond 0:137634ff4186 1670 a->len == b->len &&
ansond 0:137634ff4186 1671 x509_memcasecmp( a->p, b->p, b->len ) == 0 )
ansond 0:137634ff4186 1672 {
ansond 0:137634ff4186 1673 return( 0 );
ansond 0:137634ff4186 1674 }
ansond 0:137634ff4186 1675
ansond 0:137634ff4186 1676 return( -1 );
ansond 0:137634ff4186 1677 }
ansond 0:137634ff4186 1678
ansond 0:137634ff4186 1679 /*
ansond 0:137634ff4186 1680 * Compare two X.509 Names (aka rdnSequence).
ansond 0:137634ff4186 1681 *
ansond 0:137634ff4186 1682 * See RFC 5280 section 7.1, though we don't implement the whole algorithm:
ansond 0:137634ff4186 1683 * we sometimes return unequal when the full algorithm would return equal,
ansond 0:137634ff4186 1684 * but never the other way. (In particular, we don't do Unicode normalisation
ansond 0:137634ff4186 1685 * or space folding.)
ansond 0:137634ff4186 1686 *
ansond 0:137634ff4186 1687 * Return 0 if equal, -1 otherwise.
ansond 0:137634ff4186 1688 */
ansond 0:137634ff4186 1689 static int x509_name_cmp( const x509_name *a, const x509_name *b )
ansond 0:137634ff4186 1690 {
ansond 0:137634ff4186 1691 /* Avoid recursion, it might not be optimised by the compiler */
ansond 0:137634ff4186 1692 while( a != NULL || b != NULL )
ansond 0:137634ff4186 1693 {
ansond 0:137634ff4186 1694 if( a == NULL || b == NULL )
ansond 0:137634ff4186 1695 return( -1 );
ansond 0:137634ff4186 1696
ansond 0:137634ff4186 1697 /* type */
ansond 0:137634ff4186 1698 if( a->oid.tag != b->oid.tag ||
ansond 0:137634ff4186 1699 a->oid.len != b->oid.len ||
ansond 0:137634ff4186 1700 memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 )
ansond 0:137634ff4186 1701 {
ansond 0:137634ff4186 1702 return( -1 );
ansond 0:137634ff4186 1703 }
ansond 0:137634ff4186 1704
ansond 0:137634ff4186 1705 /* value */
ansond 0:137634ff4186 1706 if( x509_string_cmp( &a->val, &b->val ) != 0 )
ansond 0:137634ff4186 1707 return( -1 );
ansond 0:137634ff4186 1708
ansond 0:137634ff4186 1709 /* structure of the list of sets */
ansond 0:137634ff4186 1710 if( a->next_merged != b->next_merged )
ansond 0:137634ff4186 1711 return( -1 );
ansond 0:137634ff4186 1712
ansond 0:137634ff4186 1713 a = a->next;
ansond 0:137634ff4186 1714 b = b->next;
ansond 0:137634ff4186 1715 }
ansond 0:137634ff4186 1716
ansond 0:137634ff4186 1717 /* a == NULL == b */
ansond 0:137634ff4186 1718 return( 0 );
ansond 0:137634ff4186 1719 }
ansond 0:137634ff4186 1720
ansond 0:137634ff4186 1721 /*
ansond 0:137634ff4186 1722 * Check if 'parent' is a suitable parent (signing CA) for 'child'.
ansond 0:137634ff4186 1723 * Return 0 if yes, -1 if not.
ansond 0:137634ff4186 1724 *
ansond 0:137634ff4186 1725 * top means parent is a locally-trusted certificate
ansond 0:137634ff4186 1726 * bottom means child is the end entity cert
ansond 0:137634ff4186 1727 */
ansond 0:137634ff4186 1728 static int x509_crt_check_parent( const x509_crt *child,
ansond 0:137634ff4186 1729 const x509_crt *parent,
ansond 0:137634ff4186 1730 int top, int bottom )
ansond 0:137634ff4186 1731 {
ansond 0:137634ff4186 1732 int need_ca_bit;
ansond 0:137634ff4186 1733
ansond 0:137634ff4186 1734 /* Parent must be the issuer */
ansond 0:137634ff4186 1735 if( x509_name_cmp( &child->issuer, &parent->subject ) != 0 )
ansond 0:137634ff4186 1736 return( -1 );
ansond 0:137634ff4186 1737
ansond 0:137634ff4186 1738 /* Parent must have the basicConstraints CA bit set as a general rule */
ansond 0:137634ff4186 1739 need_ca_bit = 1;
ansond 0:137634ff4186 1740
ansond 0:137634ff4186 1741 /* Exception: v1/v2 certificates that are locally trusted. */
ansond 0:137634ff4186 1742 if( top && parent->version < 3 )
ansond 0:137634ff4186 1743 need_ca_bit = 0;
ansond 0:137634ff4186 1744
ansond 0:137634ff4186 1745 /* Exception: self-signed end-entity certs that are locally trusted. */
ansond 0:137634ff4186 1746 if( top && bottom &&
ansond 0:137634ff4186 1747 child->raw.len == parent->raw.len &&
ansond 0:137634ff4186 1748 memcmp( child->raw.p, parent->raw.p, child->raw.len ) == 0 )
ansond 0:137634ff4186 1749 {
ansond 0:137634ff4186 1750 need_ca_bit = 0;
ansond 0:137634ff4186 1751 }
ansond 0:137634ff4186 1752
ansond 0:137634ff4186 1753 if( need_ca_bit && ! parent->ca_istrue )
ansond 0:137634ff4186 1754 return( -1 );
ansond 0:137634ff4186 1755
ansond 0:137634ff4186 1756 #if defined(POLARSSL_X509_CHECK_KEY_USAGE)
ansond 0:137634ff4186 1757 if( need_ca_bit &&
ansond 0:137634ff4186 1758 x509_crt_check_key_usage( parent, KU_KEY_CERT_SIGN ) != 0 )
ansond 0:137634ff4186 1759 {
ansond 0:137634ff4186 1760 return( -1 );
ansond 0:137634ff4186 1761 }
ansond 0:137634ff4186 1762 #endif
ansond 0:137634ff4186 1763
ansond 0:137634ff4186 1764 return( 0 );
ansond 0:137634ff4186 1765 }
ansond 0:137634ff4186 1766
ansond 0:137634ff4186 1767 static int x509_crt_verify_top(
ansond 0:137634ff4186 1768 x509_crt *child, x509_crt *trust_ca,
ansond 0:137634ff4186 1769 x509_crl *ca_crl, int path_cnt, int *flags,
ansond 0:137634ff4186 1770 int (*f_vrfy)(void *, x509_crt *, int, int *),
ansond 0:137634ff4186 1771 void *p_vrfy )
ansond 0:137634ff4186 1772 {
ansond 0:137634ff4186 1773 int ret;
ansond 0:137634ff4186 1774 int ca_flags = 0, check_path_cnt;
ansond 0:137634ff4186 1775 unsigned char hash[POLARSSL_MD_MAX_SIZE];
ansond 0:137634ff4186 1776 const md_info_t *md_info;
ansond 0:137634ff4186 1777
ansond 0:137634ff4186 1778 if( x509_time_expired( &child->valid_to ) )
ansond 0:137634ff4186 1779 *flags |= BADCERT_EXPIRED;
ansond 0:137634ff4186 1780
ansond 0:137634ff4186 1781 if( x509_time_future( &child->valid_from ) )
ansond 0:137634ff4186 1782 *flags |= BADCERT_FUTURE;
ansond 0:137634ff4186 1783
ansond 0:137634ff4186 1784 /*
ansond 0:137634ff4186 1785 * Child is the top of the chain. Check against the trust_ca list.
ansond 0:137634ff4186 1786 */
ansond 0:137634ff4186 1787 *flags |= BADCERT_NOT_TRUSTED;
ansond 0:137634ff4186 1788
ansond 0:137634ff4186 1789 md_info = md_info_from_type( child->sig_md );
ansond 0:137634ff4186 1790 if( md_info == NULL )
ansond 0:137634ff4186 1791 {
ansond 0:137634ff4186 1792 /*
ansond 0:137634ff4186 1793 * Cannot check 'unknown', no need to try any CA
ansond 0:137634ff4186 1794 */
ansond 0:137634ff4186 1795 trust_ca = NULL;
ansond 0:137634ff4186 1796 }
ansond 0:137634ff4186 1797 else
ansond 0:137634ff4186 1798 md( md_info, child->tbs.p, child->tbs.len, hash );
ansond 0:137634ff4186 1799
ansond 0:137634ff4186 1800 for( /* trust_ca */ ; trust_ca != NULL; trust_ca = trust_ca->next )
ansond 0:137634ff4186 1801 {
ansond 0:137634ff4186 1802 if( x509_crt_check_parent( child, trust_ca, 1, path_cnt == 0 ) != 0 )
ansond 0:137634ff4186 1803 continue;
ansond 0:137634ff4186 1804
ansond 0:137634ff4186 1805 check_path_cnt = path_cnt + 1;
ansond 0:137634ff4186 1806
ansond 0:137634ff4186 1807 /*
ansond 0:137634ff4186 1808 * Reduce check_path_cnt to check against if top of the chain is
ansond 0:137634ff4186 1809 * the same as the trusted CA
ansond 0:137634ff4186 1810 */
ansond 0:137634ff4186 1811 if( child->subject_raw.len == trust_ca->subject_raw.len &&
ansond 0:137634ff4186 1812 memcmp( child->subject_raw.p, trust_ca->subject_raw.p,
ansond 0:137634ff4186 1813 child->issuer_raw.len ) == 0 )
ansond 0:137634ff4186 1814 {
ansond 0:137634ff4186 1815 check_path_cnt--;
ansond 0:137634ff4186 1816 }
ansond 0:137634ff4186 1817
ansond 0:137634ff4186 1818 if( trust_ca->max_pathlen > 0 &&
ansond 0:137634ff4186 1819 trust_ca->max_pathlen < check_path_cnt )
ansond 0:137634ff4186 1820 {
ansond 0:137634ff4186 1821 continue;
ansond 0:137634ff4186 1822 }
ansond 0:137634ff4186 1823
ansond 0:137634ff4186 1824 if( pk_verify_ext( child->sig_pk, child->sig_opts, &trust_ca->pk,
ansond 0:137634ff4186 1825 child->sig_md, hash, md_info->size,
ansond 0:137634ff4186 1826 child->sig.p, child->sig.len ) != 0 )
ansond 0:137634ff4186 1827 {
ansond 0:137634ff4186 1828 continue;
ansond 0:137634ff4186 1829 }
ansond 0:137634ff4186 1830
ansond 0:137634ff4186 1831 /*
ansond 0:137634ff4186 1832 * Top of chain is signed by a trusted CA
ansond 0:137634ff4186 1833 */
ansond 0:137634ff4186 1834 *flags &= ~BADCERT_NOT_TRUSTED;
ansond 0:137634ff4186 1835 break;
ansond 0:137634ff4186 1836 }
ansond 0:137634ff4186 1837
ansond 0:137634ff4186 1838 /*
ansond 0:137634ff4186 1839 * If top of chain is not the same as the trusted CA send a verify request
ansond 0:137634ff4186 1840 * to the callback for any issues with validity and CRL presence for the
ansond 0:137634ff4186 1841 * trusted CA certificate.
ansond 0:137634ff4186 1842 */
ansond 0:137634ff4186 1843 if( trust_ca != NULL &&
ansond 0:137634ff4186 1844 ( child->subject_raw.len != trust_ca->subject_raw.len ||
ansond 0:137634ff4186 1845 memcmp( child->subject_raw.p, trust_ca->subject_raw.p,
ansond 0:137634ff4186 1846 child->issuer_raw.len ) != 0 ) )
ansond 0:137634ff4186 1847 {
ansond 0:137634ff4186 1848 #if defined(POLARSSL_X509_CRL_PARSE_C)
ansond 0:137634ff4186 1849 /* Check trusted CA's CRL for the chain's top crt */
ansond 0:137634ff4186 1850 *flags |= x509_crt_verifycrl( child, trust_ca, ca_crl );
ansond 0:137634ff4186 1851 #else
ansond 0:137634ff4186 1852 ((void) ca_crl);
ansond 0:137634ff4186 1853 #endif
ansond 0:137634ff4186 1854
ansond 0:137634ff4186 1855 if( x509_time_expired( &trust_ca->valid_to ) )
ansond 0:137634ff4186 1856 ca_flags |= BADCERT_EXPIRED;
ansond 0:137634ff4186 1857
ansond 0:137634ff4186 1858 if( x509_time_future( &trust_ca->valid_from ) )
ansond 0:137634ff4186 1859 ca_flags |= BADCERT_FUTURE;
ansond 0:137634ff4186 1860
ansond 0:137634ff4186 1861 if( NULL != f_vrfy )
ansond 0:137634ff4186 1862 {
ansond 0:137634ff4186 1863 if( ( ret = f_vrfy( p_vrfy, trust_ca, path_cnt + 1,
ansond 0:137634ff4186 1864 &ca_flags ) ) != 0 )
ansond 0:137634ff4186 1865 {
ansond 0:137634ff4186 1866 return( ret );
ansond 0:137634ff4186 1867 }
ansond 0:137634ff4186 1868 }
ansond 0:137634ff4186 1869 }
ansond 0:137634ff4186 1870
ansond 0:137634ff4186 1871 /* Call callback on top cert */
ansond 0:137634ff4186 1872 if( NULL != f_vrfy )
ansond 0:137634ff4186 1873 {
ansond 0:137634ff4186 1874 if( ( ret = f_vrfy( p_vrfy, child, path_cnt, flags ) ) != 0 )
ansond 0:137634ff4186 1875 return( ret );
ansond 0:137634ff4186 1876 }
ansond 0:137634ff4186 1877
ansond 0:137634ff4186 1878 *flags |= ca_flags;
ansond 0:137634ff4186 1879
ansond 0:137634ff4186 1880 return( 0 );
ansond 0:137634ff4186 1881 }
ansond 0:137634ff4186 1882
ansond 0:137634ff4186 1883 static int x509_crt_verify_child(
ansond 0:137634ff4186 1884 x509_crt *child, x509_crt *parent, x509_crt *trust_ca,
ansond 0:137634ff4186 1885 x509_crl *ca_crl, int path_cnt, int *flags,
ansond 0:137634ff4186 1886 int (*f_vrfy)(void *, x509_crt *, int, int *),
ansond 0:137634ff4186 1887 void *p_vrfy )
ansond 0:137634ff4186 1888 {
ansond 0:137634ff4186 1889 int ret;
ansond 0:137634ff4186 1890 int parent_flags = 0;
ansond 0:137634ff4186 1891 unsigned char hash[POLARSSL_MD_MAX_SIZE];
ansond 0:137634ff4186 1892 x509_crt *grandparent;
ansond 0:137634ff4186 1893 const md_info_t *md_info;
ansond 0:137634ff4186 1894
ansond 0:137634ff4186 1895 /* path_cnt is 0 for the first intermediate CA */
ansond 0:137634ff4186 1896 if( 1 + path_cnt > POLARSSL_X509_MAX_INTERMEDIATE_CA )
ansond 0:137634ff4186 1897 {
ansond 0:137634ff4186 1898 *flags |= BADCERT_NOT_TRUSTED;
ansond 0:137634ff4186 1899 return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
ansond 0:137634ff4186 1900 }
ansond 0:137634ff4186 1901
ansond 0:137634ff4186 1902 if( x509_time_expired( &child->valid_to ) )
ansond 0:137634ff4186 1903 *flags |= BADCERT_EXPIRED;
ansond 0:137634ff4186 1904
ansond 0:137634ff4186 1905 if( x509_time_future( &child->valid_from ) )
ansond 0:137634ff4186 1906 *flags |= BADCERT_FUTURE;
ansond 0:137634ff4186 1907
ansond 0:137634ff4186 1908 md_info = md_info_from_type( child->sig_md );
ansond 0:137634ff4186 1909 if( md_info == NULL )
ansond 0:137634ff4186 1910 {
ansond 0:137634ff4186 1911 /*
ansond 0:137634ff4186 1912 * Cannot check 'unknown' hash
ansond 0:137634ff4186 1913 */
ansond 0:137634ff4186 1914 *flags |= BADCERT_NOT_TRUSTED;
ansond 0:137634ff4186 1915 }
ansond 0:137634ff4186 1916 else
ansond 0:137634ff4186 1917 {
ansond 0:137634ff4186 1918 md( md_info, child->tbs.p, child->tbs.len, hash );
ansond 0:137634ff4186 1919
ansond 0:137634ff4186 1920 if( pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk,
ansond 0:137634ff4186 1921 child->sig_md, hash, md_info->size,
ansond 0:137634ff4186 1922 child->sig.p, child->sig.len ) != 0 )
ansond 0:137634ff4186 1923 {
ansond 0:137634ff4186 1924 *flags |= BADCERT_NOT_TRUSTED;
ansond 0:137634ff4186 1925 }
ansond 0:137634ff4186 1926 }
ansond 0:137634ff4186 1927
ansond 0:137634ff4186 1928 #if defined(POLARSSL_X509_CRL_PARSE_C)
ansond 0:137634ff4186 1929 /* Check trusted CA's CRL for the given crt */
ansond 0:137634ff4186 1930 *flags |= x509_crt_verifycrl(child, parent, ca_crl);
ansond 0:137634ff4186 1931 #endif
ansond 0:137634ff4186 1932
ansond 0:137634ff4186 1933 /* Look for a grandparent upwards the chain */
ansond 0:137634ff4186 1934 for( grandparent = parent->next;
ansond 0:137634ff4186 1935 grandparent != NULL;
ansond 0:137634ff4186 1936 grandparent = grandparent->next )
ansond 0:137634ff4186 1937 {
ansond 0:137634ff4186 1938 if( x509_crt_check_parent( parent, grandparent,
ansond 0:137634ff4186 1939 0, path_cnt == 0 ) == 0 )
ansond 0:137634ff4186 1940 break;
ansond 0:137634ff4186 1941 }
ansond 0:137634ff4186 1942
ansond 0:137634ff4186 1943 /* Is our parent part of the chain or at the top? */
ansond 0:137634ff4186 1944 if( grandparent != NULL )
ansond 0:137634ff4186 1945 {
ansond 0:137634ff4186 1946 ret = x509_crt_verify_child( parent, grandparent, trust_ca, ca_crl,
ansond 0:137634ff4186 1947 path_cnt + 1, &parent_flags, f_vrfy, p_vrfy );
ansond 0:137634ff4186 1948 if( ret != 0 )
ansond 0:137634ff4186 1949 return( ret );
ansond 0:137634ff4186 1950 }
ansond 0:137634ff4186 1951 else
ansond 0:137634ff4186 1952 {
ansond 0:137634ff4186 1953 ret = x509_crt_verify_top( parent, trust_ca, ca_crl,
ansond 0:137634ff4186 1954 path_cnt + 1, &parent_flags, f_vrfy, p_vrfy );
ansond 0:137634ff4186 1955 if( ret != 0 )
ansond 0:137634ff4186 1956 return( ret );
ansond 0:137634ff4186 1957 }
ansond 0:137634ff4186 1958
ansond 0:137634ff4186 1959 /* child is verified to be a child of the parent, call verify callback */
ansond 0:137634ff4186 1960 if( NULL != f_vrfy )
ansond 0:137634ff4186 1961 if( ( ret = f_vrfy( p_vrfy, child, path_cnt, flags ) ) != 0 )
ansond 0:137634ff4186 1962 return( ret );
ansond 0:137634ff4186 1963
ansond 0:137634ff4186 1964 *flags |= parent_flags;
ansond 0:137634ff4186 1965
ansond 0:137634ff4186 1966 return( 0 );
ansond 0:137634ff4186 1967 }
ansond 0:137634ff4186 1968
ansond 0:137634ff4186 1969 /*
ansond 0:137634ff4186 1970 * Verify the certificate validity
ansond 0:137634ff4186 1971 */
ansond 0:137634ff4186 1972 int x509_crt_verify( x509_crt *crt,
ansond 0:137634ff4186 1973 x509_crt *trust_ca,
ansond 0:137634ff4186 1974 x509_crl *ca_crl,
ansond 0:137634ff4186 1975 const char *cn, int *flags,
ansond 0:137634ff4186 1976 int (*f_vrfy)(void *, x509_crt *, int, int *),
ansond 0:137634ff4186 1977 void *p_vrfy )
ansond 0:137634ff4186 1978 {
ansond 0:137634ff4186 1979 size_t cn_len;
ansond 0:137634ff4186 1980 int ret;
ansond 0:137634ff4186 1981 int pathlen = 0;
ansond 0:137634ff4186 1982 x509_crt *parent;
ansond 0:137634ff4186 1983 x509_name *name;
ansond 0:137634ff4186 1984 x509_sequence *cur = NULL;
ansond 0:137634ff4186 1985
ansond 0:137634ff4186 1986 *flags = 0;
ansond 0:137634ff4186 1987
ansond 0:137634ff4186 1988 if( cn != NULL )
ansond 0:137634ff4186 1989 {
ansond 0:137634ff4186 1990 name = &crt->subject;
ansond 0:137634ff4186 1991 cn_len = strlen( cn );
ansond 0:137634ff4186 1992
ansond 0:137634ff4186 1993 if( crt->ext_types & EXT_SUBJECT_ALT_NAME )
ansond 0:137634ff4186 1994 {
ansond 0:137634ff4186 1995 cur = &crt->subject_alt_names;
ansond 0:137634ff4186 1996
ansond 0:137634ff4186 1997 while( cur != NULL )
ansond 0:137634ff4186 1998 {
ansond 0:137634ff4186 1999 if( cur->buf.len == cn_len &&
ansond 0:137634ff4186 2000 x509_memcasecmp( cn, cur->buf.p, cn_len ) == 0 )
ansond 0:137634ff4186 2001 break;
ansond 0:137634ff4186 2002
ansond 0:137634ff4186 2003 if( cur->buf.len > 2 &&
ansond 0:137634ff4186 2004 memcmp( cur->buf.p, "*.", 2 ) == 0 &&
ansond 0:137634ff4186 2005 x509_wildcard_verify( cn, &cur->buf ) )
ansond 0:137634ff4186 2006 break;
ansond 0:137634ff4186 2007
ansond 0:137634ff4186 2008 cur = cur->next;
ansond 0:137634ff4186 2009 }
ansond 0:137634ff4186 2010
ansond 0:137634ff4186 2011 if( cur == NULL )
ansond 0:137634ff4186 2012 *flags |= BADCERT_CN_MISMATCH;
ansond 0:137634ff4186 2013 }
ansond 0:137634ff4186 2014 else
ansond 0:137634ff4186 2015 {
ansond 0:137634ff4186 2016 while( name != NULL )
ansond 0:137634ff4186 2017 {
ansond 0:137634ff4186 2018 if( OID_CMP( OID_AT_CN, &name->oid ) )
ansond 0:137634ff4186 2019 {
ansond 0:137634ff4186 2020 if( name->val.len == cn_len &&
ansond 0:137634ff4186 2021 x509_memcasecmp( name->val.p, cn, cn_len ) == 0 )
ansond 0:137634ff4186 2022 break;
ansond 0:137634ff4186 2023
ansond 0:137634ff4186 2024 if( name->val.len > 2 &&
ansond 0:137634ff4186 2025 memcmp( name->val.p, "*.", 2 ) == 0 &&
ansond 0:137634ff4186 2026 x509_wildcard_verify( cn, &name->val ) )
ansond 0:137634ff4186 2027 break;
ansond 0:137634ff4186 2028 }
ansond 0:137634ff4186 2029
ansond 0:137634ff4186 2030 name = name->next;
ansond 0:137634ff4186 2031 }
ansond 0:137634ff4186 2032
ansond 0:137634ff4186 2033 if( name == NULL )
ansond 0:137634ff4186 2034 *flags |= BADCERT_CN_MISMATCH;
ansond 0:137634ff4186 2035 }
ansond 0:137634ff4186 2036 }
ansond 0:137634ff4186 2037
ansond 0:137634ff4186 2038 /* Look for a parent upwards the chain */
ansond 0:137634ff4186 2039 for( parent = crt->next; parent != NULL; parent = parent->next )
ansond 0:137634ff4186 2040 {
ansond 0:137634ff4186 2041 if( x509_crt_check_parent( crt, parent, 0, pathlen == 0 ) == 0 )
ansond 0:137634ff4186 2042 break;
ansond 0:137634ff4186 2043 }
ansond 0:137634ff4186 2044
ansond 0:137634ff4186 2045 /* Are we part of the chain or at the top? */
ansond 0:137634ff4186 2046 if( parent != NULL )
ansond 0:137634ff4186 2047 {
ansond 0:137634ff4186 2048 ret = x509_crt_verify_child( crt, parent, trust_ca, ca_crl,
ansond 0:137634ff4186 2049 pathlen, flags, f_vrfy, p_vrfy );
ansond 0:137634ff4186 2050 if( ret != 0 )
ansond 0:137634ff4186 2051 return( ret );
ansond 0:137634ff4186 2052 }
ansond 0:137634ff4186 2053 else
ansond 0:137634ff4186 2054 {
ansond 0:137634ff4186 2055 ret = x509_crt_verify_top( crt, trust_ca, ca_crl,
ansond 0:137634ff4186 2056 pathlen, flags, f_vrfy, p_vrfy );
ansond 0:137634ff4186 2057 if( ret != 0 )
ansond 0:137634ff4186 2058 return( ret );
ansond 0:137634ff4186 2059 }
ansond 0:137634ff4186 2060
ansond 0:137634ff4186 2061 if( *flags != 0 )
ansond 0:137634ff4186 2062 return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
ansond 0:137634ff4186 2063
ansond 0:137634ff4186 2064 return( 0 );
ansond 0:137634ff4186 2065 }
ansond 0:137634ff4186 2066
ansond 0:137634ff4186 2067 /*
ansond 0:137634ff4186 2068 * Initialize a certificate chain
ansond 0:137634ff4186 2069 */
ansond 0:137634ff4186 2070 void x509_crt_init( x509_crt *crt )
ansond 0:137634ff4186 2071 {
ansond 0:137634ff4186 2072 memset( crt, 0, sizeof(x509_crt) );
ansond 0:137634ff4186 2073 }
ansond 0:137634ff4186 2074
ansond 0:137634ff4186 2075 /*
ansond 0:137634ff4186 2076 * Unallocate all certificate data
ansond 0:137634ff4186 2077 */
ansond 0:137634ff4186 2078 void x509_crt_free( x509_crt *crt )
ansond 0:137634ff4186 2079 {
ansond 0:137634ff4186 2080 x509_crt *cert_cur = crt;
ansond 0:137634ff4186 2081 x509_crt *cert_prv;
ansond 0:137634ff4186 2082 x509_name *name_cur;
ansond 0:137634ff4186 2083 x509_name *name_prv;
ansond 0:137634ff4186 2084 x509_sequence *seq_cur;
ansond 0:137634ff4186 2085 x509_sequence *seq_prv;
ansond 0:137634ff4186 2086
ansond 0:137634ff4186 2087 if( crt == NULL )
ansond 0:137634ff4186 2088 return;
ansond 0:137634ff4186 2089
ansond 0:137634ff4186 2090 do
ansond 0:137634ff4186 2091 {
ansond 0:137634ff4186 2092 pk_free( &cert_cur->pk );
ansond 0:137634ff4186 2093
ansond 0:137634ff4186 2094 #if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT)
ansond 0:137634ff4186 2095 polarssl_free( cert_cur->sig_opts );
ansond 0:137634ff4186 2096 #endif
ansond 0:137634ff4186 2097
ansond 0:137634ff4186 2098 name_cur = cert_cur->issuer.next;
ansond 0:137634ff4186 2099 while( name_cur != NULL )
ansond 0:137634ff4186 2100 {
ansond 0:137634ff4186 2101 name_prv = name_cur;
ansond 0:137634ff4186 2102 name_cur = name_cur->next;
ansond 0:137634ff4186 2103 polarssl_zeroize( name_prv, sizeof( x509_name ) );
ansond 0:137634ff4186 2104 polarssl_free( name_prv );
ansond 0:137634ff4186 2105 }
ansond 0:137634ff4186 2106
ansond 0:137634ff4186 2107 name_cur = cert_cur->subject.next;
ansond 0:137634ff4186 2108 while( name_cur != NULL )
ansond 0:137634ff4186 2109 {
ansond 0:137634ff4186 2110 name_prv = name_cur;
ansond 0:137634ff4186 2111 name_cur = name_cur->next;
ansond 0:137634ff4186 2112 polarssl_zeroize( name_prv, sizeof( x509_name ) );
ansond 0:137634ff4186 2113 polarssl_free( name_prv );
ansond 0:137634ff4186 2114 }
ansond 0:137634ff4186 2115
ansond 0:137634ff4186 2116 seq_cur = cert_cur->ext_key_usage.next;
ansond 0:137634ff4186 2117 while( seq_cur != NULL )
ansond 0:137634ff4186 2118 {
ansond 0:137634ff4186 2119 seq_prv = seq_cur;
ansond 0:137634ff4186 2120 seq_cur = seq_cur->next;
ansond 0:137634ff4186 2121 polarssl_zeroize( seq_prv, sizeof( x509_sequence ) );
ansond 0:137634ff4186 2122 polarssl_free( seq_prv );
ansond 0:137634ff4186 2123 }
ansond 0:137634ff4186 2124
ansond 0:137634ff4186 2125 seq_cur = cert_cur->subject_alt_names.next;
ansond 0:137634ff4186 2126 while( seq_cur != NULL )
ansond 0:137634ff4186 2127 {
ansond 0:137634ff4186 2128 seq_prv = seq_cur;
ansond 0:137634ff4186 2129 seq_cur = seq_cur->next;
ansond 0:137634ff4186 2130 polarssl_zeroize( seq_prv, sizeof( x509_sequence ) );
ansond 0:137634ff4186 2131 polarssl_free( seq_prv );
ansond 0:137634ff4186 2132 }
ansond 0:137634ff4186 2133
ansond 0:137634ff4186 2134 if( cert_cur->raw.p != NULL )
ansond 0:137634ff4186 2135 {
ansond 0:137634ff4186 2136 polarssl_zeroize( cert_cur->raw.p, cert_cur->raw.len );
ansond 0:137634ff4186 2137 polarssl_free( cert_cur->raw.p );
ansond 0:137634ff4186 2138 }
ansond 0:137634ff4186 2139
ansond 0:137634ff4186 2140 cert_cur = cert_cur->next;
ansond 0:137634ff4186 2141 }
ansond 0:137634ff4186 2142 while( cert_cur != NULL );
ansond 0:137634ff4186 2143
ansond 0:137634ff4186 2144 cert_cur = crt;
ansond 0:137634ff4186 2145 do
ansond 0:137634ff4186 2146 {
ansond 0:137634ff4186 2147 cert_prv = cert_cur;
ansond 0:137634ff4186 2148 cert_cur = cert_cur->next;
ansond 0:137634ff4186 2149
ansond 0:137634ff4186 2150 polarssl_zeroize( cert_prv, sizeof( x509_crt ) );
ansond 0:137634ff4186 2151 if( cert_prv != crt )
ansond 0:137634ff4186 2152 polarssl_free( cert_prv );
ansond 0:137634ff4186 2153 }
ansond 0:137634ff4186 2154 while( cert_cur != NULL );
ansond 0:137634ff4186 2155 }
ansond 0:137634ff4186 2156
ansond 0:137634ff4186 2157 #endif /* POLARSSL_X509_CRT_PARSE_C */
ansond 0:137634ff4186 2158