| OLD | NEW |
| (Empty) |
| 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_android.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 "base/strings/string_piece.h" | |
| 15 #include "crypto/sha2.h" | |
| 16 #include "net/android/cert_verify_result_android.h" | |
| 17 #include "net/android/network_library.h" | |
| 18 #include "net/base/net_errors.h" | |
| 19 #include "net/cert/asn1_util.h" | |
| 20 #include "net/cert/cert_status_flags.h" | |
| 21 #include "net/cert/cert_verify_result.h" | |
| 22 #include "net/cert/x509_certificate.h" | |
| 23 | |
| 24 namespace net { | |
| 25 | |
| 26 namespace { | |
| 27 | |
| 28 // Returns true if the certificate verification call was successful (regardless | |
| 29 // of its result), i.e. if |verify_result| was set. Otherwise returns false. | |
| 30 bool VerifyFromAndroidTrustManager(const std::vector<std::string>& cert_bytes, | |
| 31 const std::string& hostname, | |
| 32 CertVerifyResult* verify_result) { | |
| 33 android::CertVerifyStatusAndroid status; | |
| 34 std::vector<std::string> verified_chain; | |
| 35 | |
| 36 // TODO(joth): Fetch the authentication type from SSL rather than hardcode. | |
| 37 android::VerifyX509CertChain(cert_bytes, "RSA", hostname, | |
| 38 &status, &verify_result->is_issued_by_known_root, | |
| 39 &verified_chain); | |
| 40 switch (status) { | |
| 41 case android::CERT_VERIFY_STATUS_ANDROID_FAILED: | |
| 42 return false; | |
| 43 case android::CERT_VERIFY_STATUS_ANDROID_OK: | |
| 44 break; | |
| 45 case android::CERT_VERIFY_STATUS_ANDROID_NO_TRUSTED_ROOT: | |
| 46 verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID; | |
| 47 break; | |
| 48 case android::CERT_VERIFY_STATUS_ANDROID_EXPIRED: | |
| 49 case android::CERT_VERIFY_STATUS_ANDROID_NOT_YET_VALID: | |
| 50 verify_result->cert_status |= CERT_STATUS_DATE_INVALID; | |
| 51 break; | |
| 52 case android::CERT_VERIFY_STATUS_ANDROID_UNABLE_TO_PARSE: | |
| 53 verify_result->cert_status |= CERT_STATUS_INVALID; | |
| 54 break; | |
| 55 case android::CERT_VERIFY_STATUS_ANDROID_INCORRECT_KEY_USAGE: | |
| 56 verify_result->cert_status |= CERT_STATUS_INVALID; | |
| 57 break; | |
| 58 default: | |
| 59 NOTREACHED(); | |
| 60 verify_result->cert_status |= CERT_STATUS_INVALID; | |
| 61 break; | |
| 62 } | |
| 63 | |
| 64 // Save the verified chain. | |
| 65 if (!verified_chain.empty()) { | |
| 66 std::vector<base::StringPiece> verified_chain_pieces(verified_chain.size()); | |
| 67 for (size_t i = 0; i < verified_chain.size(); i++) { | |
| 68 verified_chain_pieces[i] = base::StringPiece(verified_chain[i]); | |
| 69 } | |
| 70 scoped_refptr<X509Certificate> verified_cert = | |
| 71 X509Certificate::CreateFromDERCertChain(verified_chain_pieces); | |
| 72 if (verified_cert.get()) | |
| 73 verify_result->verified_cert = verified_cert; | |
| 74 } | |
| 75 | |
| 76 // Extract the algorithm information from the certs | |
| 77 X509Certificate::OSCertHandles chain; | |
| 78 const X509Certificate::OSCertHandles& intermediates = | |
| 79 verify_result->verified_cert->GetIntermediateCertificates(); | |
| 80 chain.push_back(verify_result->verified_cert->os_cert_handle()); | |
| 81 chain.insert(chain.end(), intermediates.begin(), intermediates.end()); | |
| 82 | |
| 83 // If the chain successfully verified, ignore the trust anchor (the last | |
| 84 // certificate). Otherwise, assume the chain is partial. This is not entirely | |
| 85 // correct, as a full chain may have been constructed and then failed to | |
| 86 // validate. However, if that is the case, the more serious error will | |
| 87 // override any SHA-1 considerations. | |
| 88 size_t correction_for_root = | |
| 89 (status == android::CERT_VERIFY_STATUS_ANDROID_OK) ? 1 : 0; | |
| 90 for (size_t i = 0; i < chain.size() - correction_for_root; ++i) { | |
| 91 int sig_alg = OBJ_obj2nid(chain[i]->sig_alg->algorithm); | |
| 92 if (sig_alg == NID_md2WithRSAEncryption) { | |
| 93 verify_result->has_md2 = true; | |
| 94 } else if (sig_alg == NID_md4WithRSAEncryption) { | |
| 95 verify_result->has_md4 = true; | |
| 96 } else if (sig_alg == NID_md5WithRSAEncryption || | |
| 97 sig_alg == NID_md5WithRSA) { | |
| 98 verify_result->has_md5 = true; | |
| 99 } else if (sig_alg == NID_sha1WithRSAEncryption || | |
| 100 sig_alg == NID_dsaWithSHA || sig_alg == NID_dsaWithSHA1 || | |
| 101 sig_alg == NID_dsaWithSHA1_2 || sig_alg == NID_sha1WithRSA || | |
| 102 sig_alg == NID_ecdsa_with_SHA1) { | |
| 103 verify_result->has_sha1 = true; | |
| 104 } | |
| 105 } | |
| 106 | |
| 107 // Extract the public key hashes. | |
| 108 for (size_t i = 0; i < verified_chain.size(); i++) { | |
| 109 base::StringPiece spki_bytes; | |
| 110 if (!asn1::ExtractSPKIFromDERCert(verified_chain[i], &spki_bytes)) | |
| 111 continue; | |
| 112 | |
| 113 HashValue sha1(HASH_VALUE_SHA1); | |
| 114 base::SHA1HashBytes(reinterpret_cast<const uint8*>(spki_bytes.data()), | |
| 115 spki_bytes.size(), sha1.data()); | |
| 116 verify_result->public_key_hashes.push_back(sha1); | |
| 117 | |
| 118 HashValue sha256(HASH_VALUE_SHA256); | |
| 119 crypto::SHA256HashString(spki_bytes, sha256.data(), crypto::kSHA256Length); | |
| 120 verify_result->public_key_hashes.push_back(sha256); | |
| 121 } | |
| 122 | |
| 123 return true; | |
| 124 } | |
| 125 | |
| 126 bool GetChainDEREncodedBytes(X509Certificate* cert, | |
| 127 std::vector<std::string>* chain_bytes) { | |
| 128 X509Certificate::OSCertHandle cert_handle = cert->os_cert_handle(); | |
| 129 X509Certificate::OSCertHandles cert_handles = | |
| 130 cert->GetIntermediateCertificates(); | |
| 131 | |
| 132 // Make sure the peer's own cert is the first in the chain, if it's not | |
| 133 // already there. | |
| 134 if (cert_handles.empty() || cert_handles[0] != cert_handle) | |
| 135 cert_handles.insert(cert_handles.begin(), cert_handle); | |
| 136 | |
| 137 chain_bytes->reserve(cert_handles.size()); | |
| 138 for (X509Certificate::OSCertHandles::const_iterator it = | |
| 139 cert_handles.begin(); it != cert_handles.end(); ++it) { | |
| 140 std::string cert_bytes; | |
| 141 if(!X509Certificate::GetDEREncoded(*it, &cert_bytes)) | |
| 142 return false; | |
| 143 chain_bytes->push_back(cert_bytes); | |
| 144 } | |
| 145 return true; | |
| 146 } | |
| 147 | |
| 148 } // namespace | |
| 149 | |
| 150 CertVerifyProcAndroid::CertVerifyProcAndroid() {} | |
| 151 | |
| 152 CertVerifyProcAndroid::~CertVerifyProcAndroid() {} | |
| 153 | |
| 154 bool CertVerifyProcAndroid::SupportsAdditionalTrustAnchors() const { | |
| 155 return false; | |
| 156 } | |
| 157 | |
| 158 int CertVerifyProcAndroid::VerifyInternal( | |
| 159 X509Certificate* cert, | |
| 160 const std::string& hostname, | |
| 161 int flags, | |
| 162 CRLSet* crl_set, | |
| 163 const CertificateList& additional_trust_anchors, | |
| 164 CertVerifyResult* verify_result) { | |
| 165 if (!cert->VerifyNameMatch(hostname, | |
| 166 &verify_result->common_name_fallback_used)) { | |
| 167 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; | |
| 168 } | |
| 169 | |
| 170 std::vector<std::string> cert_bytes; | |
| 171 if (!GetChainDEREncodedBytes(cert, &cert_bytes)) | |
| 172 return ERR_CERT_INVALID; | |
| 173 if (!VerifyFromAndroidTrustManager(cert_bytes, hostname, verify_result)) { | |
| 174 NOTREACHED(); | |
| 175 return ERR_FAILED; | |
| 176 } | |
| 177 if (IsCertStatusError(verify_result->cert_status)) | |
| 178 return MapCertStatusToNetError(verify_result->cert_status); | |
| 179 | |
| 180 return OK; | |
| 181 } | |
| 182 | |
| 183 } // namespace net | |
| OLD | NEW |