| 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 #include <openssl/dsa.h> | 9 #include <openssl/dsa.h> |
| 10 #include <openssl/ec.h> | 10 #include <openssl/ec.h> |
| 11 #include <openssl/engine.h> | 11 #include <openssl/engine.h> |
| 12 #include <openssl/err.h> | 12 #include <openssl/err.h> |
| 13 #include <openssl/evp.h> | 13 #include <openssl/evp.h> |
| 14 #include <openssl/rsa.h> | 14 #include <openssl/rsa.h> |
| 15 #include <openssl/x509.h> |
| 15 | 16 |
| 16 #include "base/android/build_info.h" | 17 #include "base/android/build_info.h" |
| 17 #include "base/android/jni_android.h" | 18 #include "base/android/jni_android.h" |
| 18 #include "base/android/scoped_java_ref.h" | 19 #include "base/android/scoped_java_ref.h" |
| 19 #include "base/basictypes.h" | 20 #include "base/basictypes.h" |
| 20 #include "base/lazy_instance.h" | 21 #include "base/lazy_instance.h" |
| 21 #include "base/logging.h" | 22 #include "base/logging.h" |
| 22 #include "crypto/openssl_util.h" | 23 #include "crypto/openssl_util.h" |
| 23 #include "net/android/keystore.h" | 24 #include "net/android/keystore.h" |
| 24 #include "net/android/legacy_openssl.h" | 25 #include "net/android/legacy_openssl.h" |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 59 // that's referenced by the key using |EX_DATA|. | 60 // that's referenced by the key using |EX_DATA|. |
| 60 | 61 |
| 61 using base::android::ScopedJavaGlobalRef; | 62 using base::android::ScopedJavaGlobalRef; |
| 62 using base::android::ScopedJavaLocalRef; | 63 using base::android::ScopedJavaLocalRef; |
| 63 | 64 |
| 64 namespace net { | 65 namespace net { |
| 65 namespace android { | 66 namespace android { |
| 66 | 67 |
| 67 namespace { | 68 namespace { |
| 68 | 69 |
| 70 using ScopedPKCS8_PRIV_KEY_INFO = |
| 71 crypto::ScopedOpenSSL<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free>::Type; |
| 72 |
| 69 extern const RSA_METHOD android_rsa_method; | 73 extern const RSA_METHOD android_rsa_method; |
| 70 extern const ECDSA_METHOD android_ecdsa_method; | 74 extern const ECDSA_METHOD android_ecdsa_method; |
| 71 | 75 |
| 72 // KeyExData contains the data that is contained in the EX_DATA of the RSA, DSA | 76 // KeyExData contains the data that is contained in the EX_DATA of the RSA, DSA |
| 73 // and ECDSA objects that are created to wrap Android system keys. | 77 // and ECDSA objects that are created to wrap Android system keys. |
| 74 struct KeyExData { | 78 struct KeyExData { |
| 75 // private_key contains a reference to a Java, private-key object. | 79 // private_key contains a reference to a Java, private-key object. |
| 76 jobject private_key; | 80 jobject private_key; |
| 77 // legacy_rsa, if not NULL, points to an RSA* in the system's OpenSSL (which | 81 // legacy_rsa, if not NULL, points to an RSA* in the system's OpenSSL (which |
| 78 // might not be ABI compatible with Chromium). | 82 // might not be ABI compatible with Chromium). |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 311 | 315 |
| 312 // Setup an EVP_PKEY to wrap an existing platform RSA PrivateKey object. | 316 // Setup an EVP_PKEY to wrap an existing platform RSA PrivateKey object. |
| 313 // |private_key| is the JNI reference (local or global) to the object. | 317 // |private_key| is the JNI reference (local or global) to the object. |
| 314 // |legacy_rsa|, if non-NULL, is a pointer to the system OpenSSL RSA object | 318 // |legacy_rsa|, if non-NULL, is a pointer to the system OpenSSL RSA object |
| 315 // backing |private_key|. This parameter is only used for Android < 4.2 to | 319 // backing |private_key|. This parameter is only used for Android < 4.2 to |
| 316 // implement key operations not exposed by the platform. | 320 // implement key operations not exposed by the platform. |
| 317 // Returns a new EVP_PKEY on success, NULL otherwise. | 321 // Returns a new EVP_PKEY on success, NULL otherwise. |
| 318 // On success, this creates a new global JNI reference to the object | 322 // On success, this creates a new global JNI reference to the object |
| 319 // that is owned by and destroyed with the EVP_PKEY. I.e. caller can | 323 // that is owned by and destroyed with the EVP_PKEY. I.e. caller can |
| 320 // free |private_key| after the call. | 324 // free |private_key| after the call. |
| 321 crypto::ScopedEVP_PKEY GetRsaPkeyWrapper(jobject private_key, | 325 crypto::ScopedEVP_PKEY CreateRsaPkeyWrapper( |
| 322 AndroidRSA* legacy_rsa) { | 326 jobject private_key, |
| 327 AndroidRSA* legacy_rsa, |
| 328 const crypto::OpenSSLErrStackTracer& tracer) { |
| 323 crypto::ScopedRSA rsa( | 329 crypto::ScopedRSA rsa( |
| 324 RSA_new_method(global_boringssl_engine.Get().engine())); | 330 RSA_new_method(global_boringssl_engine.Get().engine())); |
| 325 | 331 |
| 326 ScopedJavaGlobalRef<jobject> global_key; | 332 ScopedJavaGlobalRef<jobject> global_key; |
| 327 global_key.Reset(NULL, private_key); | 333 global_key.Reset(NULL, private_key); |
| 328 if (global_key.is_null()) { | 334 if (global_key.is_null()) { |
| 329 LOG(ERROR) << "Could not create global JNI reference"; | 335 LOG(ERROR) << "Could not create global JNI reference"; |
| 330 return crypto::ScopedEVP_PKEY(); | 336 return crypto::ScopedEVP_PKEY(); |
| 331 } | 337 } |
| 332 | 338 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 380 private: | 386 private: |
| 381 ScopedJavaGlobalRef<jobject> engine_; | 387 ScopedJavaGlobalRef<jobject> engine_; |
| 382 }; | 388 }; |
| 383 | 389 |
| 384 void LeakEngine(jobject private_key) { | 390 void LeakEngine(jobject private_key) { |
| 385 static base::LazyInstance<KeystoreEngineWorkaround>::Leaky s_instance = | 391 static base::LazyInstance<KeystoreEngineWorkaround>::Leaky s_instance = |
| 386 LAZY_INSTANCE_INITIALIZER; | 392 LAZY_INSTANCE_INITIALIZER; |
| 387 s_instance.Get().LeakEngine(private_key); | 393 s_instance.Get().LeakEngine(private_key); |
| 388 } | 394 } |
| 389 | 395 |
| 390 // Setup an EVP_PKEY to wrap an existing platform RSA PrivateKey object | 396 // Creates an EVP_PKEY wrapper corresponding to the RSA key |
| 391 // for Android 4.0 to 4.1.x. Must only be used on Android < 4.2. | 397 // |private_key|. Returns nullptr on failure. |
| 392 // |private_key| is a JNI reference (local or global) to the object. | 398 crypto::ScopedEVP_PKEY GetRsaPkeyWrapper(jobject private_key) { |
| 393 // |pkey| is the EVP_PKEY to setup as a wrapper. | 399 const int kAndroid42ApiLevel = 17; |
| 394 // Returns true on success, false otherwise. | 400 crypto::OpenSSLErrStackTracer tracer(FROM_HERE); |
| 395 crypto::ScopedEVP_PKEY GetRsaLegacyKey(jobject private_key) { | 401 |
| 402 if (base::android::BuildInfo::GetInstance()->sdk_int() >= |
| 403 kAndroid42ApiLevel) { |
| 404 return CreateRsaPkeyWrapper(private_key, nullptr, tracer); |
| 405 } |
| 406 |
| 407 // Route around platform bug: if Android < 4.2, then |
| 408 // base::android::RawSignDigestWithPrivateKey() cannot work, so instead, try |
| 409 // to get the system OpenSSL's EVP_PKEY begin this PrivateKey object. |
| 396 AndroidEVP_PKEY* sys_pkey = | 410 AndroidEVP_PKEY* sys_pkey = |
| 397 GetOpenSSLSystemHandleForPrivateKey(private_key); | 411 GetOpenSSLSystemHandleForPrivateKey(private_key); |
| 398 if (sys_pkey != NULL) { | 412 if (sys_pkey != NULL) { |
| 399 if (sys_pkey->type != ANDROID_EVP_PKEY_RSA) { | 413 if (sys_pkey->type != ANDROID_EVP_PKEY_RSA) { |
| 400 LOG(ERROR) << "Private key has wrong type!"; | 414 LOG(ERROR) << "Private key has wrong type!"; |
| 401 return crypto::ScopedEVP_PKEY(); | 415 return nullptr; |
| 402 } | 416 } |
| 403 | 417 |
| 404 AndroidRSA* sys_rsa = sys_pkey->pkey.rsa; | 418 AndroidRSA* sys_rsa = sys_pkey->pkey.rsa; |
| 405 if (sys_rsa->engine) { | 419 if (sys_rsa->engine) { |
| 406 // |private_key| may not have an engine if the PrivateKey did not come | 420 // |private_key| may not have an engine if the PrivateKey did not come |
| 407 // from the key store, such as in unit tests. | 421 // from the key store, such as in unit tests. |
| 408 if (strcmp(sys_rsa->engine->id, "keystore") == 0) { | 422 if (strcmp(sys_rsa->engine->id, "keystore") == 0) { |
| 409 LeakEngine(private_key); | 423 LeakEngine(private_key); |
| 410 } else { | 424 } else { |
| 411 NOTREACHED(); | 425 NOTREACHED(); |
| 412 } | 426 } |
| 413 } | 427 } |
| 414 | 428 |
| 415 return GetRsaPkeyWrapper(private_key, sys_rsa); | 429 return CreateRsaPkeyWrapper(private_key, sys_rsa, tracer); |
| 416 } | 430 } |
| 417 | 431 |
| 418 // GetOpenSSLSystemHandleForPrivateKey() will fail on Android 4.0.3 and | 432 // GetOpenSSLSystemHandleForPrivateKey() will fail on Android 4.0.3 and |
| 419 // earlier. However, it is possible to get the key content with | 433 // earlier. However, it is possible to get the key content with |
| 420 // PrivateKey.getEncoded() on these platforms. Note that this method may | 434 // PrivateKey.getEncoded() on these platforms. Note that this method may |
| 421 // return NULL on 4.0.4 and later. | 435 // return false on 4.0.4 and later. |
| 422 std::vector<uint8> encoded; | 436 std::vector<uint8_t> encoded; |
| 423 if (!GetPrivateKeyEncodedBytes(private_key, &encoded)) { | 437 if (!GetPrivateKeyEncodedBytes(private_key, &encoded) || encoded.empty()) { |
| 424 LOG(ERROR) << "Can't get private key data!"; | 438 LOG(ERROR) << "Can't get private key data!"; |
| 425 return crypto::ScopedEVP_PKEY(); | 439 return nullptr; |
| 426 } | 440 } |
| 427 const unsigned char* p = | 441 const uint8_t* p = &encoded[0]; |
| 428 reinterpret_cast<const unsigned char*>(&encoded[0]); | 442 ScopedPKCS8_PRIV_KEY_INFO pkcs8( |
| 429 int len = static_cast<int>(encoded.size()); | 443 d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, encoded.size())); |
| 430 crypto::ScopedEVP_PKEY pkey(d2i_AutoPrivateKey(NULL, &p, len)); | 444 if (!pkcs8.get() || p != &encoded[0] + encoded.size()) { |
| 431 if (!pkey) { | 445 LOG(ERROR) << "Can't decode PrivateKeyInfo"; |
| 432 LOG(ERROR) << "Can't convert private key data!"; | 446 return nullptr; |
| 433 return crypto::ScopedEVP_PKEY(); | 447 } |
| 448 crypto::ScopedEVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get())); |
| 449 if (!pkey || EVP_PKEY_id(pkey.get()) != EVP_PKEY_RSA) { |
| 450 LOG(ERROR) << "Can't decode RSA key"; |
| 451 return nullptr; |
| 434 } | 452 } |
| 435 return pkey.Pass(); | 453 return pkey.Pass(); |
| 436 } | 454 } |
| 437 | 455 |
| 438 // Custom ECDSA_METHOD that uses the platform APIs. | 456 // Custom ECDSA_METHOD that uses the platform APIs. |
| 439 // Note that for now, only signing through ECDSA_sign() is really supported. | 457 // Note that for now, only signing through ECDSA_sign() is really supported. |
| 440 // all other method pointers are either stubs returning errors, or no-ops. | 458 // all other method pointers are either stubs returning errors, or no-ops. |
| 441 | 459 |
| 442 jobject EcKeyGetKey(const EC_KEY* ec_key) { | 460 jobject EcKeyGetKey(const EC_KEY* ec_key) { |
| 443 KeyExData* ex_data = reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data( | 461 KeyExData* ex_data = reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data( |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 496 return 0; | 514 return 0; |
| 497 } | 515 } |
| 498 | 516 |
| 499 // Setup an EVP_PKEY to wrap an existing platform PrivateKey object. | 517 // Setup an EVP_PKEY to wrap an existing platform PrivateKey object. |
| 500 // |private_key| is the JNI reference (local or global) to the object. | 518 // |private_key| is the JNI reference (local or global) to the object. |
| 501 // Returns a new EVP_PKEY on success, NULL otherwise. | 519 // Returns a new EVP_PKEY on success, NULL otherwise. |
| 502 // On success, this creates a global JNI reference to the object that | 520 // On success, this creates a global JNI reference to the object that |
| 503 // is owned by and destroyed with the EVP_PKEY. I.e. the caller shall | 521 // is owned by and destroyed with the EVP_PKEY. I.e. the caller shall |
| 504 // always free |private_key| after the call. | 522 // always free |private_key| after the call. |
| 505 crypto::ScopedEVP_PKEY GetEcdsaPkeyWrapper(jobject private_key) { | 523 crypto::ScopedEVP_PKEY GetEcdsaPkeyWrapper(jobject private_key) { |
| 524 crypto::OpenSSLErrStackTracer tracer(FROM_HERE); |
| 506 crypto::ScopedEC_KEY ec_key( | 525 crypto::ScopedEC_KEY ec_key( |
| 507 EC_KEY_new_method(global_boringssl_engine.Get().engine())); | 526 EC_KEY_new_method(global_boringssl_engine.Get().engine())); |
| 508 | 527 |
| 509 ScopedJavaGlobalRef<jobject> global_key; | 528 ScopedJavaGlobalRef<jobject> global_key; |
| 510 global_key.Reset(NULL, private_key); | 529 global_key.Reset(NULL, private_key); |
| 511 if (global_key.is_null()) { | 530 if (global_key.is_null()) { |
| 512 LOG(ERROR) << "Can't create global JNI reference"; | 531 LOG(ERROR) << "Can't create global JNI reference"; |
| 513 return crypto::ScopedEVP_PKEY(); | 532 return crypto::ScopedEVP_PKEY(); |
| 514 } | 533 } |
| 515 | 534 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 546 NULL /* finish */, | 565 NULL /* finish */, |
| 547 EcdsaMethodGroupOrderSize, | 566 EcdsaMethodGroupOrderSize, |
| 548 EcdsaMethodSign, | 567 EcdsaMethodSign, |
| 549 EcdsaMethodVerify, | 568 EcdsaMethodVerify, |
| 550 ECDSA_FLAG_OPAQUE, | 569 ECDSA_FLAG_OPAQUE, |
| 551 }; | 570 }; |
| 552 | 571 |
| 553 } // namespace | 572 } // namespace |
| 554 | 573 |
| 555 crypto::ScopedEVP_PKEY GetOpenSSLPrivateKeyWrapper(jobject private_key) { | 574 crypto::ScopedEVP_PKEY GetOpenSSLPrivateKeyWrapper(jobject private_key) { |
| 556 const int kAndroid42ApiLevel = 17; | |
| 557 | |
| 558 // Create sub key type, depending on private key's algorithm type. | 575 // Create sub key type, depending on private key's algorithm type. |
| 559 PrivateKeyType key_type = GetPrivateKeyType(private_key); | 576 PrivateKeyType key_type = GetPrivateKeyType(private_key); |
| 560 switch (key_type) { | 577 switch (key_type) { |
| 561 case PRIVATE_KEY_TYPE_RSA: | 578 case PRIVATE_KEY_TYPE_RSA: |
| 562 // Route around platform bug: if Android < 4.2, then | 579 return GetRsaPkeyWrapper(private_key); |
| 563 // base::android::RawSignDigestWithPrivateKey() cannot work, so | |
| 564 // instead, obtain a raw EVP_PKEY* to the system object | |
| 565 // backing this PrivateKey object. | |
| 566 if (base::android::BuildInfo::GetInstance()->sdk_int() < | |
| 567 kAndroid42ApiLevel) { | |
| 568 return GetRsaLegacyKey(private_key); | |
| 569 } else { | |
| 570 // Running on Android 4.2. | |
| 571 return GetRsaPkeyWrapper(private_key, NULL); | |
| 572 } | |
| 573 case PRIVATE_KEY_TYPE_ECDSA: | 580 case PRIVATE_KEY_TYPE_ECDSA: |
| 574 return GetEcdsaPkeyWrapper(private_key); | 581 return GetEcdsaPkeyWrapper(private_key); |
| 575 default: | 582 default: |
| 576 LOG(WARNING) | 583 LOG(WARNING) |
| 577 << "GetOpenSSLPrivateKeyWrapper() called with invalid key type"; | 584 << "GetOpenSSLPrivateKeyWrapper() called with invalid key type"; |
| 578 return crypto::ScopedEVP_PKEY(); | 585 return nullptr; |
| 579 } | 586 } |
| 580 } | 587 } |
| 581 | 588 |
| 582 } // namespace android | 589 } // namespace android |
| 583 } // namespace net | 590 } // namespace net |
| OLD | NEW |