Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1782)

Side by Side Diff: net/ssl/ssl_platform_key_android.cc

Issue 2291213002: Remove ENGINE indirection from Android SSLPrivateKey. (Closed)
Patch Set: Fix WebView build Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/ssl/ssl_platform_key.h" 5 #include "net/ssl/ssl_platform_key_android.h"
6 6
7 #include <openssl/digest.h> 7 #include <openssl/ecdsa.h>
8 #include <openssl/evp.h> 8 #include <openssl/rsa.h>
9 #include <strings.h>
9 10
11 #include <memory>
10 #include <utility> 12 #include <utility>
13 #include <vector>
11 14
15 #include "base/android/build_info.h"
16 #include "base/android/scoped_java_ref.h"
17 #include "base/lazy_instance.h"
12 #include "base/logging.h" 18 #include "base/logging.h"
13 #include "base/macros.h" 19 #include "base/macros.h"
14 #include "base/memory/ptr_util.h" 20 #include "base/memory/ptr_util.h"
15 #include "crypto/scoped_openssl_types.h" 21 #include "crypto/scoped_openssl_types.h"
22 #include "net/android/keystore.h"
23 #include "net/android/legacy_openssl.h"
16 #include "net/base/net_errors.h" 24 #include "net/base/net_errors.h"
17 #include "net/ssl/openssl_client_key_store.h" 25 #include "net/ssl/openssl_client_key_store.h"
26 #include "net/ssl/ssl_platform_key.h"
18 #include "net/ssl/ssl_platform_key_task_runner.h" 27 #include "net/ssl/ssl_platform_key_task_runner.h"
19 #include "net/ssl/ssl_private_key.h"
20 #include "net/ssl/threaded_ssl_private_key.h" 28 #include "net/ssl/threaded_ssl_private_key.h"
21 29
30 using base::android::ScopedJavaGlobalRef;
31 using base::android::ScopedJavaLocalRef;
32
22 namespace net { 33 namespace net {
23 34
24 namespace { 35 namespace {
25 36
37 // On Android < 4.2, the libkeystore.so ENGINE uses CRYPTO_EX_DATA and is not
38 // added to the global engine list. If all references to it are dropped, OpenSSL
39 // will dlclose the module, leaving a dangling function pointer in the RSA
40 // CRYPTO_EX_DATA class. To work around this, leak an extra reference to the
41 // ENGINE we extract in GetRsaLegacyKey.
42 //
43 // In 4.2, this change avoids the problem:
44 // https://android.googlesource.com/platform/libcore/+/106a8928fb4249f2f3d4dba1d ddbe73ca5cb3d61
45 //
46 // https://crbug.com/381465
47 class KeystoreEngineWorkaround {
48 public:
49 KeystoreEngineWorkaround() {}
50
51 void LeakEngine(jobject key) {
52 if (!engine_.is_null())
53 return;
54 ScopedJavaLocalRef<jobject> engine =
55 android::GetOpenSSLEngineForPrivateKey(key);
56 if (engine.is_null()) {
57 NOTREACHED();
58 return;
59 }
60 engine_.Reset(engine);
61 }
62
63 private:
64 ScopedJavaGlobalRef<jobject> engine_;
65 };
66
67 void LeakEngine(jobject private_key) {
68 static base::LazyInstance<KeystoreEngineWorkaround>::Leaky s_instance =
69 LAZY_INSTANCE_INITIALIZER;
70 s_instance.Get().LeakEngine(private_key);
71 }
72
26 class SSLPlatformKeyAndroid : public ThreadedSSLPrivateKey::Delegate { 73 class SSLPlatformKeyAndroid : public ThreadedSSLPrivateKey::Delegate {
27 public: 74 public:
28 SSLPlatformKeyAndroid(crypto::ScopedEVP_PKEY key, SSLPrivateKey::Type type) 75 SSLPlatformKeyAndroid(SSLPrivateKey::Type type,
29 : key_(std::move(key)), type_(type) {} 76 jobject key,
77 size_t max_length,
78 android::AndroidRSA* legacy_rsa)
79 : type_(type), max_length_(max_length), legacy_rsa_(legacy_rsa) {
80 key_.Reset(nullptr, key);
81 }
30 82
31 ~SSLPlatformKeyAndroid() override {} 83 ~SSLPlatformKeyAndroid() override {}
32 84
33 SSLPrivateKey::Type GetType() override { return type_; } 85 SSLPrivateKey::Type GetType() override { return type_; }
34 86
35 std::vector<SSLPrivateKey::Hash> GetDigestPreferences() override { 87 std::vector<SSLPrivateKey::Hash> GetDigestPreferences() override {
36 static const SSLPrivateKey::Hash kHashes[] = { 88 static const SSLPrivateKey::Hash kHashes[] = {
37 SSLPrivateKey::Hash::SHA512, SSLPrivateKey::Hash::SHA384, 89 SSLPrivateKey::Hash::SHA512, SSLPrivateKey::Hash::SHA384,
38 SSLPrivateKey::Hash::SHA256, SSLPrivateKey::Hash::SHA1}; 90 SSLPrivateKey::Hash::SHA256, SSLPrivateKey::Hash::SHA1};
39 return std::vector<SSLPrivateKey::Hash>(kHashes, 91 return std::vector<SSLPrivateKey::Hash>(kHashes,
40 kHashes + arraysize(kHashes)); 92 kHashes + arraysize(kHashes));
41 } 93 }
42 94
43 size_t GetMaxSignatureLengthInBytes() override { 95 size_t GetMaxSignatureLengthInBytes() override { return max_length_; }
44 return EVP_PKEY_size(key_.get());
45 }
46 96
47 Error SignDigest(SSLPrivateKey::Hash hash, 97 Error SignDigest(SSLPrivateKey::Hash hash,
48 const base::StringPiece& input, 98 const base::StringPiece& input_in,
49 std::vector<uint8_t>* signature) override { 99 std::vector<uint8_t>* signature) override {
50 crypto::ScopedEVP_PKEY_CTX ctx = 100 base::StringPiece input = input_in;
51 crypto::ScopedEVP_PKEY_CTX(EVP_PKEY_CTX_new(key_.get(), NULL));
52 if (!ctx)
53 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
54 if (!EVP_PKEY_sign_init(ctx.get()))
55 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
56 101
102 // Prepend the DigestInfo for RSA.
103 crypto::ScopedOpenSSLBytes digest_info_storage;
57 if (type_ == SSLPrivateKey::Type::RSA) { 104 if (type_ == SSLPrivateKey::Type::RSA) {
58 const EVP_MD* digest = nullptr; 105 int hash_nid = NID_undef;
59 switch (hash) { 106 switch (hash) {
60 case SSLPrivateKey::Hash::MD5_SHA1: 107 case SSLPrivateKey::Hash::MD5_SHA1:
61 digest = EVP_md5_sha1(); 108 hash_nid = NID_md5_sha1;
62 break; 109 break;
63 case SSLPrivateKey::Hash::SHA1: 110 case SSLPrivateKey::Hash::SHA1:
64 digest = EVP_sha1(); 111 hash_nid = NID_sha1;
65 break; 112 break;
66 case SSLPrivateKey::Hash::SHA256: 113 case SSLPrivateKey::Hash::SHA256:
67 digest = EVP_sha256(); 114 hash_nid = NID_sha256;
68 break; 115 break;
69 case SSLPrivateKey::Hash::SHA384: 116 case SSLPrivateKey::Hash::SHA384:
70 digest = EVP_sha384(); 117 hash_nid = NID_sha384;
71 break; 118 break;
72 case SSLPrivateKey::Hash::SHA512: 119 case SSLPrivateKey::Hash::SHA512:
73 digest = EVP_sha512(); 120 hash_nid = NID_sha512;
74 break; 121 break;
75 default:
76 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
77 } 122 }
78 DCHECK(digest); 123 DCHECK_NE(NID_undef, hash_nid);
79 if (!EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PADDING)) 124
125 uint8_t* digest_info;
126 size_t digest_info_len;
127 int is_alloced;
128 if (!RSA_add_pkcs1_prefix(
129 &digest_info, &digest_info_len, &is_alloced, hash_nid,
130 reinterpret_cast<const uint8_t*>(input.data()), input.size())) {
80 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; 131 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
81 if (!EVP_PKEY_CTX_set_signature_md(ctx.get(), digest)) 132 }
82 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; 133
134 if (is_alloced)
135 digest_info_storage.reset(digest_info);
136 input = base::StringPiece(reinterpret_cast<const char*>(digest_info),
137 digest_info_len);
83 } 138 }
84 139
85 const uint8_t* input_ptr = reinterpret_cast<const uint8_t*>(input.data()); 140 // Pre-4.2 legacy codepath.
86 size_t input_len = input.size(); 141 if (legacy_rsa_) {
87 size_t sig_len = 0; 142 signature->resize(max_length_);
88 if (!EVP_PKEY_sign(ctx.get(), NULL, &sig_len, input_ptr, input_len)) 143 int ret = legacy_rsa_->meth->rsa_priv_enc(
89 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; 144 input.size(), reinterpret_cast<const uint8_t*>(input.data()),
90 signature->resize(sig_len); 145 signature->data(), legacy_rsa_, android::ANDROID_RSA_PKCS1_PADDING);
91 if (!EVP_PKEY_sign(ctx.get(), signature->data(), &sig_len, input_ptr, 146 if (ret < 0) {
92 input_len)) { 147 LOG(WARNING) << "Could not sign message with legacy RSA key!";
148 // System OpenSSL will use a separate error queue, so it is still
149 // necessary to push a new error.
150 //
151 // TODO(davidben): It would be good to also clear the system error queue
152 // if there were some way to convince Java to do it. (Without going
153 // through Java, it's difficult to get a handle on a system OpenSSL
154 // function; dlopen loads a second copy.)
155 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
156 }
157 signature->resize(ret);
158 return OK;
159 }
160
161 if (!android::RawSignDigestWithPrivateKey(key_.obj(), input, signature)) {
162 LOG(WARNING) << "Could not sign message with private key!";
93 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; 163 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
94 } 164 }
95
96 signature->resize(sig_len);
97
98 return OK; 165 return OK;
99 } 166 }
100 167
101 private: 168 private:
102 crypto::ScopedEVP_PKEY key_;
103 SSLPrivateKey::Type type_; 169 SSLPrivateKey::Type type_;
170 ScopedJavaGlobalRef<jobject> key_;
171 size_t max_length_;
172 android::AndroidRSA* legacy_rsa_;
104 173
105 DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyAndroid); 174 DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyAndroid);
106 }; 175 };
107 176
108 scoped_refptr<SSLPrivateKey> WrapOpenSSLPrivateKey(crypto::ScopedEVP_PKEY key) { 177 // VectorBignumSize returns the number of bytes needed to represent the bignum
109 if (!key) 178 // given in |v|, i.e. the length of |v| less any leading zero bytes.
179 size_t VectorBignumSize(const std::vector<uint8_t>& v) {
180 size_t size = v.size();
181 // Ignore any leading zero bytes.
182 for (size_t i = 0; i < v.size() && v[i] == 0; i++) {
183 size--;
184 }
185 return size;
186 }
187
188 std::unique_ptr<SSLPlatformKeyAndroid> CreateRsaKey(jobject key) {
189 android::AndroidRSA* sys_rsa = nullptr;
190 const int kAndroid42ApiLevel = 17;
191 if (base::android::BuildInfo::GetInstance()->sdk_int() < kAndroid42ApiLevel) {
192 // Route around platform limitations: if Android < 4.2, then
193 // base::android::RawSignDigestWithPrivateKey() cannot work, so try to get
194 // the system OpenSSL's EVP_PKEY backing this PrivateKey object.
195 android::AndroidEVP_PKEY* sys_pkey =
196 android::GetOpenSSLSystemHandleForPrivateKey(key);
197 if (!sys_pkey)
198 return nullptr;
199
200 if (sys_pkey->type != android::ANDROID_EVP_PKEY_RSA) {
201 LOG(ERROR) << "Private key has wrong type!";
202 return nullptr;
203 }
204
205 sys_rsa = sys_pkey->pkey.rsa;
206 if (sys_rsa->engine) {
207 // |private_key| may not have an engine if the PrivateKey did not come
208 // from the key store, such as in unit tests.
209 if (strcmp(sys_rsa->engine->id, "keystore") == 0) {
210 LeakEngine(key);
211 } else {
212 NOTREACHED();
213 }
214 }
215 }
216
217 std::vector<uint8_t> modulus;
218 if (!android::GetRSAKeyModulus(key, &modulus)) {
219 LOG(ERROR) << "Failed to get private key modulus";
110 return nullptr; 220 return nullptr;
221 }
111 222
112 SSLPrivateKey::Type type; 223 return base::MakeUnique<SSLPlatformKeyAndroid>(
113 switch (EVP_PKEY_id(key.get())) { 224 SSLPrivateKey::Type::RSA, key, VectorBignumSize(modulus), sys_rsa);
114 case EVP_PKEY_RSA: 225 }
115 type = SSLPrivateKey::Type::RSA; 226
116 break; 227 std::unique_ptr<SSLPlatformKeyAndroid> CreateEcdsaKey(jobject key) {
117 case EVP_PKEY_EC: 228 std::vector<uint8_t> order;
118 type = SSLPrivateKey::Type::ECDSA; 229 if (!android::GetECKeyOrder(key, &order)) {
119 break; 230 LOG(ERROR) << "Can't extract order parameter from EC private key";
120 default: 231 return nullptr;
121 LOG(ERROR) << "Unknown key type: " << EVP_PKEY_id(key.get());
122 return nullptr;
123 } 232 }
124 return make_scoped_refptr(new ThreadedSSLPrivateKey( 233
125 base::WrapUnique(new SSLPlatformKeyAndroid(std::move(key), type)), 234 return base::MakeUnique<SSLPlatformKeyAndroid>(
126 GetSSLPlatformKeyTaskRunner())); 235 SSLPrivateKey::Type::ECDSA, key,
236 ECDSA_SIG_max_len(VectorBignumSize(order)), nullptr);
127 } 237 }
128 238
129 } // namespace 239 } // namespace
130 240
241 scoped_refptr<SSLPrivateKey> WrapJavaPrivateKey(jobject key) {
242 std::unique_ptr<SSLPlatformKeyAndroid> delegate;
243 switch (android::GetPrivateKeyType(key)) {
244 case android::PRIVATE_KEY_TYPE_RSA:
245 delegate = CreateRsaKey(key);
246 break;
247 case android::PRIVATE_KEY_TYPE_ECDSA:
248 delegate = CreateEcdsaKey(key);
249 break;
250 default:
251 LOG(WARNING) << "GetPrivateKeyType() returned invalid type";
252 return nullptr;
253 }
254
255 return make_scoped_refptr(new ThreadedSSLPrivateKey(
256 std::move(delegate), GetSSLPlatformKeyTaskRunner()));
257 }
258
131 scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey( 259 scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey(
132 X509Certificate* certificate) { 260 X509Certificate* certificate) {
133 crypto::ScopedEVP_PKEY key = 261 return OpenSSLClientKeyStore::GetInstance()->FetchClientCertPrivateKey(
134 OpenSSLClientKeyStore::GetInstance()->FetchClientCertPrivateKey( 262 certificate);
135 certificate);
136 return WrapOpenSSLPrivateKey(std::move(key));
137 } 263 }
138 264
139 } // namespace net 265 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698