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 |
11 // not be a concern for Chromium which always links against its own | 11 // not be a concern for Chromium which always links against its own |
12 // version of the library on Android. | 12 // version of the library on Android. |
13 #include <openssl/crypto/ecdsa/ecs_locl.h> | 13 #include <openssl/crypto/ecdsa/ecs_locl.h> |
14 // And this one is needed for the EC_GROUP definition. | 14 // And this one is needed for the EC_GROUP definition. |
15 #include <openssl/crypto/ec/ec_lcl.h> | 15 #include <openssl/crypto/ec/ec_lcl.h> |
16 #include <openssl/dsa.h> | 16 #include <openssl/dsa.h> |
17 #include <openssl/ec.h> | 17 #include <openssl/ec.h> |
18 #include <openssl/engine.h> | 18 #include <openssl/engine.h> |
19 #include <openssl/evp.h> | 19 #include <openssl/evp.h> |
20 #include <openssl/rsa.h> | 20 #include <openssl/rsa.h> |
21 | 21 |
22 #include "base/android/build_info.h" | 22 #include "base/android/build_info.h" |
23 #include "base/android/jni_android.h" | 23 #include "base/android/jni_android.h" |
24 #include "base/android/scoped_java_ref.h" | 24 #include "base/android/scoped_java_ref.h" |
25 #include "base/basictypes.h" | 25 #include "base/basictypes.h" |
26 #include "base/lazy_instance.h" | 26 #include "base/lazy_instance.h" |
27 #include "base/logging.h" | 27 #include "base/logging.h" |
28 #include "crypto/openssl_util.h" | 28 #include "crypto/openssl_util.h" |
| 29 #include "crypto/scoped_openssl_types.h" |
29 #include "net/android/keystore.h" | 30 #include "net/android/keystore.h" |
30 #include "net/ssl/ssl_client_cert_type.h" | 31 #include "net/ssl/ssl_client_cert_type.h" |
31 | 32 |
32 // IMPORTANT NOTE: The following code will currently only work when used | 33 // IMPORTANT NOTE: The following code will currently only work when used |
33 // to implement client certificate support with OpenSSL. That's because | 34 // to implement client certificate support with OpenSSL. That's because |
34 // only the signing operations used in this use case are implemented here. | 35 // only the signing operations used in this use case are implemented here. |
35 // | 36 // |
36 // Generally speaking, OpenSSL provides many different ways to sign | 37 // Generally speaking, OpenSSL provides many different ways to sign |
37 // digests. This code doesn't support all these cases, only the ones that | 38 // digests. This code doesn't support all these cases, only the ones that |
38 // are required to sign the digest during the OpenSSL handshake for TLS. | 39 // are required to sign the digest during the OpenSSL handshake for TLS. |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 // default for a lot of operations. Very fortunately, this is not needed | 95 // default for a lot of operations. Very fortunately, this is not needed |
95 // here, which saves a lot of complexity. | 96 // here, which saves a lot of complexity. |
96 | 97 |
97 using base::android::ScopedJavaGlobalRef; | 98 using base::android::ScopedJavaGlobalRef; |
98 | 99 |
99 namespace net { | 100 namespace net { |
100 namespace android { | 101 namespace android { |
101 | 102 |
102 namespace { | 103 namespace { |
103 | 104 |
104 typedef crypto::ScopedOpenSSL<EVP_PKEY, EVP_PKEY_free> ScopedEVP_PKEY; | 105 typedef crypto::ScopedOpenSSL<EC_GROUP, EC_GROUP_free>::Type ScopedEC_GROUP; |
105 typedef crypto::ScopedOpenSSL<RSA, RSA_free> ScopedRSA; | |
106 typedef crypto::ScopedOpenSSL<DSA, DSA_free> ScopedDSA; | |
107 typedef crypto::ScopedOpenSSL<EC_KEY, EC_KEY_free> ScopedEC_KEY; | |
108 typedef crypto::ScopedOpenSSL<EC_GROUP, EC_GROUP_free> ScopedEC_GROUP; | |
109 | 106 |
110 // Custom RSA_METHOD that uses the platform APIs. | 107 // Custom RSA_METHOD that uses the platform APIs. |
111 // Note that for now, only signing through RSA_sign() is really supported. | 108 // Note that for now, only signing through RSA_sign() is really supported. |
112 // all other method pointers are either stubs returning errors, or no-ops. | 109 // all other method pointers are either stubs returning errors, or no-ops. |
113 // See <openssl/rsa.h> for exact declaration of RSA_METHOD. | 110 // See <openssl/rsa.h> for exact declaration of RSA_METHOD. |
114 | 111 |
115 int RsaMethodPubEnc(int flen, | 112 int RsaMethodPubEnc(int flen, |
116 const unsigned char* from, | 113 const unsigned char* from, |
117 unsigned char* to, | 114 unsigned char* to, |
118 RSA* rsa, | 115 RSA* rsa, |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
276 // Setup an EVP_PKEY to wrap an existing platform RSA PrivateKey object. | 273 // Setup an EVP_PKEY to wrap an existing platform RSA PrivateKey object. |
277 // |private_key| is the JNI reference (local or global) to the object. | 274 // |private_key| is the JNI reference (local or global) to the object. |
278 // |pkey| is the EVP_PKEY to setup as a wrapper. | 275 // |pkey| is the EVP_PKEY to setup as a wrapper. |
279 // Returns true on success, false otherwise. | 276 // Returns true on success, false otherwise. |
280 // On success, this creates a new global JNI reference to the object | 277 // On success, this creates a new global JNI reference to the object |
281 // that is owned by and destroyed with the EVP_PKEY. I.e. caller can | 278 // that is owned by and destroyed with the EVP_PKEY. I.e. caller can |
282 // free |private_key| after the call. | 279 // free |private_key| after the call. |
283 // IMPORTANT: The EVP_PKEY will *only* work on Android >= 4.2. For older | 280 // IMPORTANT: The EVP_PKEY will *only* work on Android >= 4.2. For older |
284 // platforms, use GetRsaLegacyKey() instead. | 281 // platforms, use GetRsaLegacyKey() instead. |
285 bool GetRsaPkeyWrapper(jobject private_key, EVP_PKEY* pkey) { | 282 bool GetRsaPkeyWrapper(jobject private_key, EVP_PKEY* pkey) { |
286 ScopedRSA rsa(RSA_new()); | 283 crypto::ScopedRSA rsa(RSA_new()); |
287 RSA_set_method(rsa.get(), &android_rsa_method); | 284 RSA_set_method(rsa.get(), &android_rsa_method); |
288 | 285 |
289 // HACK: RSA_size() doesn't work with custom RSA_METHODs. To ensure that | 286 // HACK: RSA_size() doesn't work with custom RSA_METHODs. To ensure that |
290 // it will return the right value, set the 'n' field of the RSA object | 287 // it will return the right value, set the 'n' field of the RSA object |
291 // to match the private key's modulus. | 288 // to match the private key's modulus. |
292 std::vector<uint8> modulus; | 289 std::vector<uint8> modulus; |
293 if (!GetRSAKeyModulus(private_key, &modulus)) { | 290 if (!GetRSAKeyModulus(private_key, &modulus)) { |
294 LOG(ERROR) << "Failed to get private key modulus"; | 291 LOG(ERROR) << "Failed to get private key modulus"; |
295 return false; | 292 return false; |
296 } | 293 } |
(...skipping 23 matching lines...) Expand all Loading... |
320 // https://android.googlesource.com/platform/libcore/+/106a8928fb4249f2f3d4dba1d
ddbe73ca5cb3d61 | 317 // https://android.googlesource.com/platform/libcore/+/106a8928fb4249f2f3d4dba1d
ddbe73ca5cb3d61 |
321 // | 318 // |
322 // https://crbug.com/381465 | 319 // https://crbug.com/381465 |
323 class KeystoreEngineWorkaround { | 320 class KeystoreEngineWorkaround { |
324 public: | 321 public: |
325 KeystoreEngineWorkaround() : leaked_engine_(false) {} | 322 KeystoreEngineWorkaround() : leaked_engine_(false) {} |
326 | 323 |
327 void LeakRsaEngine(EVP_PKEY* pkey) { | 324 void LeakRsaEngine(EVP_PKEY* pkey) { |
328 if (leaked_engine_) | 325 if (leaked_engine_) |
329 return; | 326 return; |
330 ScopedRSA rsa(EVP_PKEY_get1_RSA(pkey)); | 327 crypto::ScopedRSA rsa(EVP_PKEY_get1_RSA(pkey)); |
331 if (!rsa.get() || | 328 if (!rsa.get() || |
332 !rsa.get()->engine || | 329 !rsa.get()->engine || |
333 strcmp(ENGINE_get_id(rsa.get()->engine), "keystore") || | 330 strcmp(ENGINE_get_id(rsa.get()->engine), "keystore") || |
334 !ENGINE_init(rsa.get()->engine)) { | 331 !ENGINE_init(rsa.get()->engine)) { |
335 NOTREACHED(); | 332 NOTREACHED(); |
336 return; | 333 return; |
337 } | 334 } |
338 leaked_engine_ = true; | 335 leaked_engine_ = true; |
339 } | 336 } |
340 | 337 |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
473 /* .dsa_keygen = */ NULL | 470 /* .dsa_keygen = */ NULL |
474 }; | 471 }; |
475 | 472 |
476 // Setup an EVP_PKEY to wrap an existing DSA platform PrivateKey object. | 473 // Setup an EVP_PKEY to wrap an existing DSA platform PrivateKey object. |
477 // |private_key| is a JNI reference (local or global) to the object. | 474 // |private_key| is a JNI reference (local or global) to the object. |
478 // |pkey| is the EVP_PKEY to setup as a wrapper. | 475 // |pkey| is the EVP_PKEY to setup as a wrapper. |
479 // Returns true on success, false otherwise. | 476 // Returns true on success, false otherwise. |
480 // On success, this creates a global JNI reference to the same object | 477 // On success, this creates a global JNI reference to the same object |
481 // that will be owned by and destroyed with the EVP_PKEY. | 478 // that will be owned by and destroyed with the EVP_PKEY. |
482 bool GetDsaPkeyWrapper(jobject private_key, EVP_PKEY* pkey) { | 479 bool GetDsaPkeyWrapper(jobject private_key, EVP_PKEY* pkey) { |
483 ScopedDSA dsa(DSA_new()); | 480 crypto::ScopedDSA dsa(DSA_new()); |
484 DSA_set_method(dsa.get(), &android_dsa_method); | 481 DSA_set_method(dsa.get(), &android_dsa_method); |
485 | 482 |
486 // DSA_size() doesn't work with custom DSA_METHODs. To ensure it | 483 // DSA_size() doesn't work with custom DSA_METHODs. To ensure it |
487 // returns the right value, set the 'q' field in the DSA object to | 484 // returns the right value, set the 'q' field in the DSA object to |
488 // match the parameter from the platform key. | 485 // match the parameter from the platform key. |
489 std::vector<uint8> q; | 486 std::vector<uint8> q; |
490 if (!GetDSAKeyParamQ(private_key, &q)) { | 487 if (!GetDSAKeyParamQ(private_key, &q)) { |
491 LOG(ERROR) << "Can't extract Q parameter from DSA private key"; | 488 LOG(ERROR) << "Can't extract Q parameter from DSA private key"; |
492 return false; | 489 return false; |
493 } | 490 } |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
642 }; | 639 }; |
643 | 640 |
644 // Setup an EVP_PKEY to wrap an existing platform PrivateKey object. | 641 // Setup an EVP_PKEY to wrap an existing platform PrivateKey object. |
645 // |private_key| is the JNI reference (local or global) to the object. | 642 // |private_key| is the JNI reference (local or global) to the object. |
646 // |pkey| is the EVP_PKEY to setup as a wrapper. | 643 // |pkey| is the EVP_PKEY to setup as a wrapper. |
647 // Returns true on success, false otherwise. | 644 // Returns true on success, false otherwise. |
648 // On success, this creates a global JNI reference to the object that | 645 // On success, this creates a global JNI reference to the object that |
649 // is owned by and destroyed with the EVP_PKEY. I.e. the caller shall | 646 // is owned by and destroyed with the EVP_PKEY. I.e. the caller shall |
650 // always free |private_key| after the call. | 647 // always free |private_key| after the call. |
651 bool GetEcdsaPkeyWrapper(jobject private_key, EVP_PKEY* pkey) { | 648 bool GetEcdsaPkeyWrapper(jobject private_key, EVP_PKEY* pkey) { |
652 ScopedEC_KEY eckey(EC_KEY_new()); | 649 crypto::ScopedEC_KEY eckey(EC_KEY_new()); |
653 ECDSA_set_method(eckey.get(), &android_ecdsa_method); | 650 ECDSA_set_method(eckey.get(), &android_ecdsa_method); |
654 | 651 |
655 // To ensure that ECDSA_size() works properly, craft a custom EC_GROUP | 652 // To ensure that ECDSA_size() works properly, craft a custom EC_GROUP |
656 // that has the same order than the private key. | 653 // that has the same order than the private key. |
657 std::vector<uint8> order; | 654 std::vector<uint8> order; |
658 if (!GetECKeyOrder(private_key, &order)) { | 655 if (!GetECKeyOrder(private_key, &order)) { |
659 LOG(ERROR) << "Can't extract order parameter from EC private key"; | 656 LOG(ERROR) << "Can't extract order parameter from EC private key"; |
660 return false; | 657 return false; |
661 } | 658 } |
662 ScopedEC_GROUP group(EC_GROUP_new(EC_GFp_nist_method())); | 659 ScopedEC_GROUP group(EC_GROUP_new(EC_GFp_nist_method())); |
(...skipping 18 matching lines...) Expand all Loading... |
681 global_key.Release()); | 678 global_key.Release()); |
682 | 679 |
683 EVP_PKEY_assign_EC_KEY(pkey, eckey.release()); | 680 EVP_PKEY_assign_EC_KEY(pkey, eckey.release()); |
684 return true; | 681 return true; |
685 } | 682 } |
686 | 683 |
687 } // namespace | 684 } // namespace |
688 | 685 |
689 EVP_PKEY* GetOpenSSLPrivateKeyWrapper(jobject private_key) { | 686 EVP_PKEY* GetOpenSSLPrivateKeyWrapper(jobject private_key) { |
690 // Create new empty EVP_PKEY instance. | 687 // Create new empty EVP_PKEY instance. |
691 ScopedEVP_PKEY pkey(EVP_PKEY_new()); | 688 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new()); |
692 if (!pkey.get()) | 689 if (!pkey.get()) |
693 return NULL; | 690 return NULL; |
694 | 691 |
695 // Create sub key type, depending on private key's algorithm type. | 692 // Create sub key type, depending on private key's algorithm type. |
696 PrivateKeyType key_type = GetPrivateKeyType(private_key); | 693 PrivateKeyType key_type = GetPrivateKeyType(private_key); |
697 switch (key_type) { | 694 switch (key_type) { |
698 case PRIVATE_KEY_TYPE_RSA: | 695 case PRIVATE_KEY_TYPE_RSA: |
699 { | 696 { |
700 // Route around platform bug: if Android < 4.2, then | 697 // Route around platform bug: if Android < 4.2, then |
701 // base::android::RawSignDigestWithPrivateKey() cannot work, so | 698 // base::android::RawSignDigestWithPrivateKey() cannot work, so |
(...skipping 24 matching lines...) Expand all Loading... |
726 default: | 723 default: |
727 LOG(WARNING) | 724 LOG(WARNING) |
728 << "GetOpenSSLPrivateKeyWrapper() called with invalid key type"; | 725 << "GetOpenSSLPrivateKeyWrapper() called with invalid key type"; |
729 return NULL; | 726 return NULL; |
730 } | 727 } |
731 return pkey.release(); | 728 return pkey.release(); |
732 } | 729 } |
733 | 730 |
734 } // namespace android | 731 } // namespace android |
735 } // namespace net | 732 } // namespace net |
OLD | NEW |