OLD | NEW |
---|---|
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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/android/keystore_openssl.h" | 5 #include "net/android/keystore_openssl.h" |
6 | 6 |
7 #include <jni.h> | 7 #include <jni.h> |
8 #include <openssl/bn.h> | 8 #include <openssl/bn.h> |
9 // This include is required to get the ECDSA_METHOD structure definition | 9 // This include is required to get the ECDSA_METHOD structure definition |
10 // which isn't currently part of the OpenSSL official ABI. This should | 10 // which isn't currently part of the OpenSSL official ABI. This should |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
303 global_key.Reset(NULL, private_key); | 303 global_key.Reset(NULL, private_key); |
304 if (global_key.is_null()) { | 304 if (global_key.is_null()) { |
305 LOG(ERROR) << "Could not create global JNI reference"; | 305 LOG(ERROR) << "Could not create global JNI reference"; |
306 return false; | 306 return false; |
307 } | 307 } |
308 RSA_set_app_data(rsa.get(), global_key.Release()); | 308 RSA_set_app_data(rsa.get(), global_key.Release()); |
309 EVP_PKEY_assign_RSA(pkey, rsa.release()); | 309 EVP_PKEY_assign_RSA(pkey, rsa.release()); |
310 return true; | 310 return true; |
311 } | 311 } |
312 | 312 |
313 // On Android < 4.2, the libkeystore.so ENGINE uses CRYPTO_EX_DATA and is not | |
314 // added to the global engine list. If all references to it are dropped, OpenSSL | |
315 // will dlclose the module, leaving a dangling function pointer in the RSA | |
316 // CRYPTO_EX_DATA class. To work around this, leak an extra reference to the | |
317 // ENGINE we extract in GetRsaLegacyKey. | |
318 // | |
319 // In 4.2, this change avoids the problem: | |
320 // https://android.googlesource.com/platform/libcore/+/106a8928fb4249f2f3d4dba1d ddbe73ca5cb3d61 | |
321 // | |
322 // https://crbug.com/381465 | |
323 class KeystoreEngineWorkaround { | |
324 public: | |
Ryan Sleevi
2014/06/17 21:55:37
indent 1 space
davidben
2014/06/17 23:43:18
Done.
| |
325 KeystoreEngineWorkaround() : leaked_(false) {} | |
326 | |
327 void LeakRsaEngine(EVP_PKEY* pkey) { | |
328 if (leaked_) | |
329 return; | |
330 ScopedRSA rsa(EVP_PKEY_get1_RSA(pkey)); | |
331 if (!rsa.get() || | |
332 !rsa.get()->engine || | |
333 strcmp(ENGINE_get_id(rsa.get()->engine), "keystore") || | |
334 !ENGINE_init(rsa.get()->engine)) { | |
Ryan Sleevi
2014/06/17 21:55:37
Don't use get()-> for operator->
Don't use get() f
davidben
2014/06/17 23:43:17
ScopedOpenSSL doesn't actually provide a whole lot
| |
335 NOTREACHED(); | |
336 return; | |
337 } | |
338 leaked_ = true; | |
339 } | |
340 | |
341 private: | |
Ryan Sleevi
2014/06/17 21:55:37
indent 1 space
davidben
2014/06/17 23:43:17
Done.
| |
342 bool leaked_; | |
Ryan Sleevi
2014/06/17 21:55:37
s/leaked_/leaked_engine_/ perhaps?
Just so it's c
davidben
2014/06/17 23:43:17
Done.
| |
343 }; | |
344 | |
345 void LeakRsaEngine(EVP_PKEY* pkey) { | |
346 static base::LazyInstance<KeystoreEngineWorkaround> s_instance = | |
Ryan Sleevi
2014/06/17 21:55:37
this should be a ::Leaky lazy instance
davidben
2014/06/17 23:43:18
Done.
| |
347 LAZY_INSTANCE_INITIALIZER; | |
348 s_instance.Get().LeakRsaEngine(pkey); | |
349 } | |
350 | |
313 // Setup an EVP_PKEY to wrap an existing platform RSA PrivateKey object | 351 // Setup an EVP_PKEY to wrap an existing platform RSA PrivateKey object |
314 // for Android 4.0 to 4.1.x. Must only be used on Android < 4.2. | 352 // for Android 4.0 to 4.1.x. Must only be used on Android < 4.2. |
315 // |private_key| is a JNI reference (local or global) to the object. | 353 // |private_key| is a JNI reference (local or global) to the object. |
316 // |pkey| is the EVP_PKEY to setup as a wrapper. | 354 // |pkey| is the EVP_PKEY to setup as a wrapper. |
317 // Returns true on success, false otherwise. | 355 // Returns true on success, false otherwise. |
318 EVP_PKEY* GetRsaLegacyKey(jobject private_key) { | 356 EVP_PKEY* GetRsaLegacyKey(jobject private_key) { |
319 EVP_PKEY* sys_pkey = | 357 EVP_PKEY* sys_pkey = |
320 GetOpenSSLSystemHandleForPrivateKey(private_key); | 358 GetOpenSSLSystemHandleForPrivateKey(private_key); |
321 if (sys_pkey != NULL) { | 359 if (sys_pkey != NULL) { |
322 CRYPTO_add(&sys_pkey->references, 1, CRYPTO_LOCK_EVP_PKEY); | 360 CRYPTO_add(&sys_pkey->references, 1, CRYPTO_LOCK_EVP_PKEY); |
361 LeakRsaEngine(sys_pkey); | |
323 } else { | 362 } else { |
324 // GetOpenSSLSystemHandleForPrivateKey() will fail on Android | 363 // GetOpenSSLSystemHandleForPrivateKey() will fail on Android |
325 // 4.0.3 and earlier. However, it is possible to get the key | 364 // 4.0.3 and earlier. However, it is possible to get the key |
326 // content with PrivateKey.getEncoded() on these platforms. | 365 // content with PrivateKey.getEncoded() on these platforms. |
327 // Note that this method may return NULL on 4.0.4 and later. | 366 // Note that this method may return NULL on 4.0.4 and later. |
328 std::vector<uint8> encoded; | 367 std::vector<uint8> encoded; |
329 if (!GetPrivateKeyEncodedBytes(private_key, &encoded)) { | 368 if (!GetPrivateKeyEncodedBytes(private_key, &encoded)) { |
330 LOG(ERROR) << "Can't get private key data!"; | 369 LOG(ERROR) << "Can't get private key data!"; |
331 return NULL; | 370 return NULL; |
332 } | 371 } |
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
687 default: | 726 default: |
688 LOG(WARNING) | 727 LOG(WARNING) |
689 << "GetOpenSSLPrivateKeyWrapper() called with invalid key type"; | 728 << "GetOpenSSLPrivateKeyWrapper() called with invalid key type"; |
690 return NULL; | 729 return NULL; |
691 } | 730 } |
692 return pkey.release(); | 731 return pkey.release(); |
693 } | 732 } |
694 | 733 |
695 } // namespace android | 734 } // namespace android |
696 } // namespace net | 735 } // namespace net |
OLD | NEW |