1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "net/cert/cert_verify_proc_openssl.h" 6 7 #include <openssl/x509v3.h> 8 9 #include <string> 10 #include <vector> 11 12 #include "base/logging.h" 13 #include "base/sha1.h" 14 #include "crypto/openssl_util.h" 15 #include "crypto/sha2.h" 16 #include "net/base/net_errors.h" 17 #include "net/cert/asn1_util.h" 18 #include "net/cert/cert_status_flags.h" 19 #include "net/cert/cert_verifier.h" 20 #include "net/cert/cert_verify_result.h" 21 #include "net/cert/test_root_certs.h" 22 #include "net/cert/x509_certificate.h" 23 24 namespace net { 25 26 namespace { 27 28 // Maps X509_STORE_CTX_get_error() return values to our cert status flags. 29 CertStatus MapCertErrorToCertStatus(int err) { 30 switch (err) { 31 case X509_V_ERR_SUBJECT_ISSUER_MISMATCH: 32 return CERT_STATUS_COMMON_NAME_INVALID; 33 case X509_V_ERR_CERT_NOT_YET_VALID: 34 case X509_V_ERR_CERT_HAS_EXPIRED: 35 case X509_V_ERR_CRL_NOT_YET_VALID: 36 case X509_V_ERR_CRL_HAS_EXPIRED: 37 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: 38 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: 39 case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: 40 case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: 41 return CERT_STATUS_DATE_INVALID; 42 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: 43 case X509_V_ERR_UNABLE_TO_GET_CRL: 44 case X509_V_ERR_INVALID_CA: 45 case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER: 46 case X509_V_ERR_INVALID_NON_CA: 47 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: 48 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: 49 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: 50 return CERT_STATUS_AUTHORITY_INVALID; 51 #if 0 52 // TODO(bulach): what should we map to these status? 53 return CERT_STATUS_NO_REVOCATION_MECHANISM; 54 return CERT_STATUS_UNABLE_TO_CHECK_REVOCATION; 55 #endif 56 case X509_V_ERR_CERT_REVOKED: 57 return CERT_STATUS_REVOKED; 58 // All these status are mapped to CERT_STATUS_INVALID. 59 case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: 60 case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: 61 case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: 62 case X509_V_ERR_CERT_SIGNATURE_FAILURE: 63 case X509_V_ERR_CRL_SIGNATURE_FAILURE: 64 case X509_V_ERR_OUT_OF_MEM: 65 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: 66 case X509_V_ERR_CERT_CHAIN_TOO_LONG: 67 case X509_V_ERR_PATH_LENGTH_EXCEEDED: 68 case X509_V_ERR_INVALID_PURPOSE: 69 case X509_V_ERR_CERT_UNTRUSTED: 70 case X509_V_ERR_CERT_REJECTED: 71 case X509_V_ERR_AKID_SKID_MISMATCH: 72 case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: 73 case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION: 74 case X509_V_ERR_KEYUSAGE_NO_CERTSIGN: 75 case X509_V_ERR_KEYUSAGE_NO_CRL_SIGN: 76 case X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION: 77 case X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED: 78 case X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE: 79 case X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED: 80 case X509_V_ERR_INVALID_EXTENSION: 81 case X509_V_ERR_INVALID_POLICY_EXTENSION: 82 case X509_V_ERR_NO_EXPLICIT_POLICY: 83 case X509_V_ERR_UNNESTED_RESOURCE: 84 case X509_V_ERR_APPLICATION_VERIFICATION: 85 return CERT_STATUS_INVALID; 86 default: 87 NOTREACHED() << "Invalid X509 err " << err; 88 return CERT_STATUS_INVALID; 89 } 90 } 91 92 // sk_X509_free is a function-style macro, so can't be used as a template 93 // param directly. 94 void sk_X509_free_fn(STACK_OF(X509)* st) { 95 sk_X509_free(st); 96 } 97 98 void GetCertChainInfo(X509_STORE_CTX* store_ctx, 99 CertVerifyResult* verify_result) { 100 STACK_OF(X509)* chain = X509_STORE_CTX_get_chain(store_ctx); 101 X509* verified_cert = NULL; 102 std::vector<X509*> verified_chain; 103 for (int i = 0; i < sk_X509_num(chain); ++i) { 104 X509* cert = sk_X509_value(chain, i); 105 if (i == 0) { 106 verified_cert = cert; 107 } else { 108 verified_chain.push_back(cert); 109 } 110 111 // Only check the algorithm status for certificates that are not in the 112 // trust store. 113 if (i < store_ctx->last_untrusted) { 114 int sig_alg = OBJ_obj2nid(cert->sig_alg->algorithm); 115 if (sig_alg == NID_md2WithRSAEncryption) { 116 verify_result->has_md2 = true; 117 } else if (sig_alg == NID_md4WithRSAEncryption) { 118 verify_result->has_md4 = true; 119 } else if (sig_alg == NID_md5WithRSAEncryption) { 120 verify_result->has_md5 = true; 121 } 122 } 123 } 124 125 // Set verify_result->verified_cert and 126 // verify_result->is_issued_by_known_root. 127 if (verified_cert) { 128 verify_result->verified_cert = 129 X509Certificate::CreateFromHandle(verified_cert, verified_chain); 130 131 // For OpenSSL builds, only certificates used for unit tests are treated 132 // as not issued by known roots. The only way to determine whether a 133 // certificate is issued by a known root using OpenSSL is to examine 134 // distro-and-release specific hardcoded lists. 135 verify_result->is_issued_by_known_root = true; 136 if (TestRootCerts::HasInstance()) { 137 X509* root = NULL; 138 if (verified_chain.empty()) { 139 root = verified_cert; 140 } else { 141 root = verified_chain.back(); 142 } 143 TestRootCerts* root_certs = TestRootCerts::GetInstance(); 144 if (root_certs->Contains(root)) 145 verify_result->is_issued_by_known_root = false; 146 } 147 } 148 } 149 150 void AppendPublicKeyHashes(X509_STORE_CTX* store_ctx, 151 HashValueVector* hashes) { 152 STACK_OF(X509)* chain = X509_STORE_CTX_get_chain(store_ctx); 153 for (int i = 0; i < sk_X509_num(chain); ++i) { 154 X509* cert = sk_X509_value(chain, i); 155 156 std::string der_data; 157 if (!X509Certificate::GetDEREncoded(cert, &der_data)) 158 continue; 159 160 base::StringPiece der_bytes(der_data); 161 base::StringPiece spki_bytes; 162 if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki_bytes)) 163 continue; 164 165 HashValue sha1(HASH_VALUE_SHA1); 166 base::SHA1HashBytes(reinterpret_cast<const uint8*>(spki_bytes.data()), 167 spki_bytes.size(), sha1.data()); 168 hashes->push_back(sha1); 169 170 HashValue sha256(HASH_VALUE_SHA256); 171 crypto::SHA256HashString(spki_bytes, sha256.data(), crypto::kSHA256Length); 172 hashes->push_back(sha256); 173 } 174 } 175 176 } // namespace 177 178 CertVerifyProcOpenSSL::CertVerifyProcOpenSSL() {} 179 180 CertVerifyProcOpenSSL::~CertVerifyProcOpenSSL() {} 181 182 bool CertVerifyProcOpenSSL::SupportsAdditionalTrustAnchors() const { 183 return false; 184 } 185 186 int CertVerifyProcOpenSSL::VerifyInternal( 187 X509Certificate* cert, 188 const std::string& hostname, 189 int flags, 190 CRLSet* crl_set, 191 const CertificateList& additional_trust_anchors, 192 CertVerifyResult* verify_result) { 193 crypto::EnsureOpenSSLInit(); 194 195 if (!cert->VerifyNameMatch(hostname, 196 &verify_result->common_name_fallback_used)) { 197 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; 198 } 199 200 crypto::ScopedOpenSSL<X509_STORE_CTX, X509_STORE_CTX_free> ctx( 201 X509_STORE_CTX_new()); 202 203 crypto::ScopedOpenSSL<STACK_OF(X509), sk_X509_free_fn> intermediates( 204 sk_X509_new_null()); 205 if (!intermediates.get()) 206 return ERR_OUT_OF_MEMORY; 207 208 const X509Certificate::OSCertHandles& os_intermediates = 209 cert->GetIntermediateCertificates(); 210 for (X509Certificate::OSCertHandles::const_iterator it = 211 os_intermediates.begin(); it != os_intermediates.end(); ++it) { 212 if (!sk_X509_push(intermediates.get(), *it)) 213 return ERR_OUT_OF_MEMORY; 214 } 215 if (X509_STORE_CTX_init(ctx.get(), X509Certificate::cert_store(), 216 cert->os_cert_handle(), intermediates.get()) != 1) { 217 NOTREACHED(); 218 return ERR_FAILED; 219 } 220 221 if (X509_verify_cert(ctx.get()) != 1) { 222 int x509_error = X509_STORE_CTX_get_error(ctx.get()); 223 CertStatus cert_status = MapCertErrorToCertStatus(x509_error); 224 LOG(ERROR) << "X509 Verification error " 225 << X509_verify_cert_error_string(x509_error) 226 << " : " << x509_error 227 << " : " << X509_STORE_CTX_get_error_depth(ctx.get()) 228 << " : " << cert_status; 229 verify_result->cert_status |= cert_status; 230 } 231 232 GetCertChainInfo(ctx.get(), verify_result); 233 AppendPublicKeyHashes(ctx.get(), &verify_result->public_key_hashes); 234 if (IsCertStatusError(verify_result->cert_status)) 235 return MapCertStatusToNetError(verify_result->cert_status); 236 237 return OK; 238 } 239 240 } // namespace net 241