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