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"
10 #include "base/logging.h"
11 #include "base/sha1.h"
12 #include "base/strings/string_piece.h"
13 #include "crypto/sha2.h"
14 #include "net/android/cert_verify_result_android.h"
15 #include "net/android/network_library.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_verify_result.h"
20 #include "net/cert/x509_certificate.h"
26 // Returns true if the certificate verification call was successful (regardless
27 // of its result), i.e. if |verify_result| was set. Otherwise returns false.
28 bool VerifyFromAndroidTrustManager(const std::vector
<std::string
>& cert_bytes
,
29 const std::string
& hostname
,
30 CertVerifyResult
* verify_result
) {
31 android::CertVerifyStatusAndroid status
;
32 std::vector
<std::string
> verified_chain
;
34 // TODO(joth): Fetch the authentication type from SSL rather than hardcode.
35 android::VerifyX509CertChain(cert_bytes
, "RSA", hostname
,
36 &status
, &verify_result
->is_issued_by_known_root
,
39 case android::VERIFY_FAILED
:
41 case android::VERIFY_OK
:
43 case android::VERIFY_NO_TRUSTED_ROOT
:
44 verify_result
->cert_status
|= CERT_STATUS_AUTHORITY_INVALID
;
46 case android::VERIFY_EXPIRED
:
47 case android::VERIFY_NOT_YET_VALID
:
48 verify_result
->cert_status
|= CERT_STATUS_DATE_INVALID
;
50 case android::VERIFY_UNABLE_TO_PARSE
:
51 verify_result
->cert_status
|= CERT_STATUS_INVALID
;
53 case android::VERIFY_INCORRECT_KEY_USAGE
:
54 verify_result
->cert_status
|= CERT_STATUS_INVALID
;
58 verify_result
->cert_status
|= CERT_STATUS_INVALID
;
62 // Save the verified chain.
63 if (!verified_chain
.empty()) {
64 std::vector
<base::StringPiece
> verified_chain_pieces(verified_chain
.size());
65 for (size_t i
= 0; i
< verified_chain
.size(); i
++) {
66 verified_chain_pieces
[i
] = base::StringPiece(verified_chain
[i
]);
68 scoped_refptr
<X509Certificate
> verified_cert
=
69 X509Certificate::CreateFromDERCertChain(verified_chain_pieces
);
71 verify_result
->verified_cert
= verified_cert
;
74 // Extract the public key hashes.
75 for (size_t i
= 0; i
< verified_chain
.size(); i
++) {
76 base::StringPiece spki_bytes
;
77 if (!asn1::ExtractSPKIFromDERCert(verified_chain
[i
], &spki_bytes
))
80 HashValue
sha1(HASH_VALUE_SHA1
);
81 base::SHA1HashBytes(reinterpret_cast<const uint8
*>(spki_bytes
.data()),
82 spki_bytes
.size(), sha1
.data());
83 verify_result
->public_key_hashes
.push_back(sha1
);
85 HashValue
sha256(HASH_VALUE_SHA256
);
86 crypto::SHA256HashString(spki_bytes
, sha256
.data(), crypto::kSHA256Length
);
87 verify_result
->public_key_hashes
.push_back(sha256
);
93 bool GetChainDEREncodedBytes(X509Certificate
* cert
,
94 std::vector
<std::string
>* chain_bytes
) {
95 X509Certificate::OSCertHandle cert_handle
= cert
->os_cert_handle();
96 X509Certificate::OSCertHandles cert_handles
=
97 cert
->GetIntermediateCertificates();
99 // Make sure the peer's own cert is the first in the chain, if it's not
101 if (cert_handles
.empty() || cert_handles
[0] != cert_handle
)
102 cert_handles
.insert(cert_handles
.begin(), cert_handle
);
104 chain_bytes
->reserve(cert_handles
.size());
105 for (X509Certificate::OSCertHandles::const_iterator it
=
106 cert_handles
.begin(); it
!= cert_handles
.end(); ++it
) {
107 std::string cert_bytes
;
108 if(!X509Certificate::GetDEREncoded(*it
, &cert_bytes
))
110 chain_bytes
->push_back(cert_bytes
);
117 CertVerifyProcAndroid::CertVerifyProcAndroid() {}
119 CertVerifyProcAndroid::~CertVerifyProcAndroid() {}
121 bool CertVerifyProcAndroid::SupportsAdditionalTrustAnchors() const {
125 int CertVerifyProcAndroid::VerifyInternal(
126 X509Certificate
* cert
,
127 const std::string
& hostname
,
130 const CertificateList
& additional_trust_anchors
,
131 CertVerifyResult
* verify_result
) {
132 if (!cert
->VerifyNameMatch(hostname
,
133 &verify_result
->common_name_fallback_used
)) {
134 verify_result
->cert_status
|= CERT_STATUS_COMMON_NAME_INVALID
;
137 std::vector
<std::string
> cert_bytes
;
138 if (!GetChainDEREncodedBytes(cert
, &cert_bytes
))
139 return ERR_CERT_INVALID
;
140 if (!VerifyFromAndroidTrustManager(cert_bytes
, hostname
, verify_result
)) {
144 if (IsCertStatusError(verify_result
->cert_status
))
145 return MapCertStatusToNetError(verify_result
->cert_status
);