1 // Copyright 2015 The Chromium Authors
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 <string>
6 #include <vector>
7
8 #include "base/android/jni_android.h"
9 #include "base/android/jni_array.h"
10 #include "base/android/jni_string.h"
11 #include "base/test/test_support_android.h"
12 #include "components/cronet/android/cronet_test_apk_jni/MockCertVerifier_jni.h"
13 #include "crypto/sha2.h"
14 #include "net/base/net_errors.h"
15 #include "net/cert/asn1_util.h"
16 #include "net/cert/cert_verifier.h"
17 #include "net/cert/cert_verify_result.h"
18 #include "net/cert/mock_cert_verifier.h"
19 #include "net/cert/x509_util.h"
20 #include "net/test/cert_test_util.h"
21 #include "net/test/test_data_directory.h"
22
23 using base::android::JavaParamRef;
24
25 namespace cronet {
26
27 namespace {
28
29 // Populates |out_hash_value| with the SHA256 hash of the |cert| public key.
30 // Returns true on success.
CalculatePublicKeySha256(const net::X509Certificate & cert,net::HashValue * out_hash_value)31 static bool CalculatePublicKeySha256(const net::X509Certificate& cert,
32 net::HashValue* out_hash_value) {
33 // Extract the public key from the cert.
34 base::StringPiece spki_bytes;
35 if (!net::asn1::ExtractSPKIFromDERCert(
36 net::x509_util::CryptoBufferAsStringPiece(cert.cert_buffer()),
37 &spki_bytes)) {
38 LOG(INFO) << "Unable to retrieve the public key from the DER cert";
39 return false;
40 }
41 // Calculate SHA256 hash of public key bytes.
42 *out_hash_value = net::HashValue(net::HASH_VALUE_SHA256);
43 crypto::SHA256HashString(spki_bytes, out_hash_value->data(),
44 crypto::kSHA256Length);
45 return true;
46 }
47
48 } // namespace
49
JNI_MockCertVerifier_CreateMockCertVerifier(JNIEnv * env,const JavaParamRef<jobjectArray> & jcerts,const jboolean jknown_root,const JavaParamRef<jstring> & jtest_data_dir)50 static jlong JNI_MockCertVerifier_CreateMockCertVerifier(
51 JNIEnv* env,
52 const JavaParamRef<jobjectArray>& jcerts,
53 const jboolean jknown_root,
54 const JavaParamRef<jstring>& jtest_data_dir) {
55 base::FilePath test_data_dir(
56 base::android::ConvertJavaStringToUTF8(env, jtest_data_dir));
57 base::InitAndroidTestPaths(test_data_dir);
58
59 std::vector<std::string> certs;
60 base::android::AppendJavaStringArrayToStringVector(env, jcerts, &certs);
61 net::MockCertVerifier* mock_cert_verifier = new net::MockCertVerifier();
62 for (const auto& cert : certs) {
63 net::CertVerifyResult verify_result;
64 verify_result.verified_cert =
65 net::ImportCertFromFile(net::GetTestCertsDirectory(), cert);
66
67 // By default, HPKP verification is enabled for known trust roots only.
68 verify_result.is_issued_by_known_root = jknown_root;
69
70 // Calculate the public key hash and add it to the verify_result.
71 net::HashValue hashValue;
72 CHECK(CalculatePublicKeySha256(*verify_result.verified_cert.get(),
73 &hashValue));
74 verify_result.public_key_hashes.push_back(hashValue);
75
76 mock_cert_verifier->AddResultForCert(verify_result.verified_cert.get(),
77 verify_result, net::OK);
78 }
79
80 return reinterpret_cast<jlong>(mock_cert_verifier);
81 }
82
JNI_MockCertVerifier_CreateFreeForAllMockCertVerifier(JNIEnv * env)83 static jlong JNI_MockCertVerifier_CreateFreeForAllMockCertVerifier(
84 JNIEnv* env) {
85 net::MockCertVerifier* mock_cert_verifier = new net::MockCertVerifier();
86 mock_cert_verifier->set_default_result(net::OK);
87 return reinterpret_cast<jlong>(mock_cert_verifier);
88 }
89
90 } // namespace cronet
91