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.
5 #include "net/cert/cert_verify_proc_android.h"
7 #include <openssl/x509v3.h>
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"
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
;
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
,
41 case android::CERT_VERIFY_STATUS_ANDROID_FAILED
:
43 case android::CERT_VERIFY_STATUS_ANDROID_OK
:
45 case android::CERT_VERIFY_STATUS_ANDROID_NO_TRUSTED_ROOT
:
46 verify_result
->cert_status
|= CERT_STATUS_AUTHORITY_INVALID
;
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
;
52 case android::CERT_VERIFY_STATUS_ANDROID_UNABLE_TO_PARSE
:
53 verify_result
->cert_status
|= CERT_STATUS_INVALID
;
55 case android::CERT_VERIFY_STATUS_ANDROID_INCORRECT_KEY_USAGE
:
56 verify_result
->cert_status
|= CERT_STATUS_INVALID
;
60 verify_result
->cert_status
|= CERT_STATUS_INVALID
;
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
]);
70 scoped_refptr
<X509Certificate
> verified_cert
=
71 X509Certificate::CreateFromDERCertChain(verified_chain_pieces
);
72 if (verified_cert
.get())
73 verify_result
->verified_cert
= verified_cert
;
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());
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;
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
))
113 HashValue
sha1(HASH_VALUE_SHA1
);
114 base::SHA1HashBytes(reinterpret_cast<const uint8_t*>(spki_bytes
.data()),
115 spki_bytes
.size(), sha1
.data());
116 verify_result
->public_key_hashes
.push_back(sha1
);
118 HashValue
sha256(HASH_VALUE_SHA256
);
119 crypto::SHA256HashString(spki_bytes
, sha256
.data(), crypto::kSHA256Length
);
120 verify_result
->public_key_hashes
.push_back(sha256
);
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();
132 // Make sure the peer's own cert is the first in the chain, if it's not
134 if (cert_handles
.empty() || cert_handles
[0] != cert_handle
)
135 cert_handles
.insert(cert_handles
.begin(), cert_handle
);
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
))
143 chain_bytes
->push_back(cert_bytes
);
150 CertVerifyProcAndroid::CertVerifyProcAndroid() {}
152 CertVerifyProcAndroid::~CertVerifyProcAndroid() {}
154 bool CertVerifyProcAndroid::SupportsAdditionalTrustAnchors() const {
158 bool CertVerifyProcAndroid::SupportsOCSPStapling() const {
162 int CertVerifyProcAndroid::VerifyInternal(
163 X509Certificate
* cert
,
164 const std::string
& hostname
,
165 const std::string
& ocsp_response
,
168 const CertificateList
& additional_trust_anchors
,
169 CertVerifyResult
* verify_result
) {
170 if (!cert
->VerifyNameMatch(hostname
,
171 &verify_result
->common_name_fallback_used
)) {
172 verify_result
->cert_status
|= CERT_STATUS_COMMON_NAME_INVALID
;
175 std::vector
<std::string
> cert_bytes
;
176 if (!GetChainDEREncodedBytes(cert
, &cert_bytes
))
177 return ERR_CERT_INVALID
;
178 if (!VerifyFromAndroidTrustManager(cert_bytes
, hostname
, verify_result
)) {
182 if (IsCertStatusError(verify_result
->cert_status
))
183 return MapCertStatusToNetError(verify_result
->cert_status
);