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 "net/ssl/ssl_platform_key_android.h"
6
7 #include <strings.h>
8
9 #include <memory>
10 #include <utility>
11 #include <vector>
12
13 #include "base/android/scoped_java_ref.h"
14 #include "base/containers/flat_set.h"
15 #include "base/logging.h"
16 #include "net/android/keystore.h"
17 #include "net/base/net_errors.h"
18 #include "net/ssl/ssl_platform_key_util.h"
19 #include "net/ssl/threaded_ssl_private_key.h"
20 #include "third_party/abseil-cpp/absl/types/optional.h"
21 #include "third_party/boringssl/src/include/openssl/ecdsa.h"
22 #include "third_party/boringssl/src/include/openssl/evp.h"
23 #include "third_party/boringssl/src/include/openssl/mem.h"
24 #include "third_party/boringssl/src/include/openssl/nid.h"
25 #include "third_party/boringssl/src/include/openssl/rsa.h"
26 #include "third_party/boringssl/src/include/openssl/ssl.h"
27
28 using base::android::JavaRef;
29 using base::android::ScopedJavaGlobalRef;
30
31 namespace net {
32
33 namespace {
34
GetJavaAlgorithm(uint16_t algorithm)35 const char* GetJavaAlgorithm(uint16_t algorithm) {
36 switch (algorithm) {
37 case SSL_SIGN_RSA_PKCS1_SHA1:
38 return "SHA1withRSA";
39 case SSL_SIGN_RSA_PKCS1_SHA256:
40 return "SHA256withRSA";
41 case SSL_SIGN_RSA_PKCS1_SHA384:
42 return "SHA384withRSA";
43 case SSL_SIGN_RSA_PKCS1_SHA512:
44 return "SHA512withRSA";
45 case SSL_SIGN_ECDSA_SHA1:
46 return "SHA1withECDSA";
47 case SSL_SIGN_ECDSA_SECP256R1_SHA256:
48 return "SHA256withECDSA";
49 case SSL_SIGN_ECDSA_SECP384R1_SHA384:
50 return "SHA384withECDSA";
51 case SSL_SIGN_ECDSA_SECP521R1_SHA512:
52 return "SHA512withECDSA";
53 case SSL_SIGN_RSA_PSS_SHA256:
54 return "SHA256withRSA/PSS";
55 case SSL_SIGN_RSA_PSS_SHA384:
56 return "SHA384withRSA/PSS";
57 case SSL_SIGN_RSA_PSS_SHA512:
58 return "SHA512withRSA/PSS";
59 default:
60 return nullptr;
61 }
62 }
63
64 // Java's public-key encryption algorithms are mis-named. It incorrectly
65 // classifies RSA's "mode" as ECB.
66 const char kRSANoPadding[] = "RSA/ECB/NoPadding";
67
68 class SSLPlatformKeyAndroid : public ThreadedSSLPrivateKey::Delegate {
69 public:
SSLPlatformKeyAndroid(bssl::UniquePtr<EVP_PKEY> pubkey,const JavaRef<jobject> & key)70 SSLPlatformKeyAndroid(bssl::UniquePtr<EVP_PKEY> pubkey,
71 const JavaRef<jobject>& key)
72 : pubkey_(std::move(pubkey)),
73 provider_name_(android::GetPrivateKeyClassName(key)) {
74 key_.Reset(key);
75
76 absl::optional<bool> supports_rsa_no_padding;
77 for (uint16_t algorithm : SSLPrivateKey::DefaultAlgorithmPreferences(
78 EVP_PKEY_id(pubkey_.get()), true /* include PSS */)) {
79 const char* java_algorithm = GetJavaAlgorithm(algorithm);
80 if (java_algorithm &&
81 android::PrivateKeySupportsSignature(key_, java_algorithm)) {
82 preferences_.push_back(algorithm);
83 } else if (SSL_is_signature_algorithm_rsa_pss(algorithm)) {
84 // Check if we can use the fallback path instead.
85 if (!supports_rsa_no_padding) {
86 supports_rsa_no_padding =
87 android::PrivateKeySupportsCipher(key_, kRSANoPadding);
88 }
89 if (*supports_rsa_no_padding) {
90 preferences_.push_back(algorithm);
91 use_pss_fallback_.insert(algorithm);
92 }
93 }
94 }
95 }
96
97 SSLPlatformKeyAndroid(const SSLPlatformKeyAndroid&) = delete;
98 SSLPlatformKeyAndroid& operator=(const SSLPlatformKeyAndroid&) = delete;
99
100 ~SSLPlatformKeyAndroid() override = default;
101
GetProviderName()102 std::string GetProviderName() override { return provider_name_; }
103
GetAlgorithmPreferences()104 std::vector<uint16_t> GetAlgorithmPreferences() override {
105 return preferences_;
106 }
107
Sign(uint16_t algorithm,base::span<const uint8_t> input,std::vector<uint8_t> * signature)108 Error Sign(uint16_t algorithm,
109 base::span<const uint8_t> input,
110 std::vector<uint8_t>* signature) override {
111 if (use_pss_fallback_.contains(algorithm)) {
112 return SignPSSFallback(algorithm, input, signature);
113 }
114
115 const char* java_algorithm = GetJavaAlgorithm(algorithm);
116 if (!java_algorithm) {
117 LOG(ERROR) << "Unknown algorithm " << algorithm;
118 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
119 }
120 if (!android::SignWithPrivateKey(key_, java_algorithm, input, signature)) {
121 LOG(ERROR) << "Could not sign message with private key!";
122 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
123 }
124 return OK;
125 }
126
127 private:
SignPSSFallback(uint16_t algorithm,base::span<const uint8_t> input,std::vector<uint8_t> * signature)128 Error SignPSSFallback(uint16_t algorithm,
129 base::span<const uint8_t> input,
130 std::vector<uint8_t>* signature) {
131 const EVP_MD* md = SSL_get_signature_algorithm_digest(algorithm);
132 uint8_t digest[EVP_MAX_MD_SIZE];
133 unsigned digest_len;
134 if (!EVP_Digest(input.data(), input.size(), digest, &digest_len, md,
135 nullptr)) {
136 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
137 }
138
139 absl::optional<std::vector<uint8_t>> padded =
140 AddPSSPadding(pubkey_.get(), md, base::make_span(digest, digest_len));
141 if (!padded) {
142 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
143 }
144
145 if (!android::EncryptWithPrivateKey(key_, kRSANoPadding, *padded,
146 signature)) {
147 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
148 }
149 return OK;
150 }
151
152 bssl::UniquePtr<EVP_PKEY> pubkey_;
153 ScopedJavaGlobalRef<jobject> key_;
154 std::string provider_name_;
155 std::vector<uint16_t> preferences_;
156 base::flat_set<uint16_t> use_pss_fallback_;
157 };
158
159 } // namespace
160
WrapJavaPrivateKey(const X509Certificate * certificate,const JavaRef<jobject> & key)161 scoped_refptr<SSLPrivateKey> WrapJavaPrivateKey(
162 const X509Certificate* certificate,
163 const JavaRef<jobject>& key) {
164 bssl::UniquePtr<EVP_PKEY> pubkey = GetClientCertPublicKey(certificate);
165 if (!pubkey)
166 return nullptr;
167
168 return base::MakeRefCounted<ThreadedSSLPrivateKey>(
169 std::make_unique<SSLPlatformKeyAndroid>(std::move(pubkey), key),
170 GetSSLPlatformKeyTaskRunner());
171 }
172
173 } // namespace net
174