Chromium Code Reviews| 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 | 15 |
| 16 #include "base/android/build_info.h" | 16 #include "base/android/build_info.h" |
| 17 #include "base/android/jni_android.h" | 17 #include "base/android/jni_android.h" |
| 18 #include "base/android/scoped_java_ref.h" | 18 #include "base/android/scoped_java_ref.h" |
| 19 #include "base/basictypes.h" | 19 #include "base/basictypes.h" |
| 20 #include "base/lazy_instance.h" | 20 #include "base/lazy_instance.h" |
| 21 #include "base/logging.h" | 21 #include "base/logging.h" |
| 22 #include "crypto/openssl_util.h" | 22 #include "crypto/openssl_util.h" |
| 23 #include "crypto/scoped_openssl_types.h" | |
| 24 #include "net/android/keystore.h" | 23 #include "net/android/keystore.h" |
| 25 #include "net/android/legacy_openssl.h" | 24 #include "net/android/legacy_openssl.h" |
| 26 #include "net/ssl/ssl_client_cert_type.h" | 25 #include "net/ssl/ssl_client_cert_type.h" |
| 27 | 26 |
| 28 // IMPORTANT NOTE: The following code will currently only work when used | 27 // IMPORTANT NOTE: The following code will currently only work when used |
| 29 // to implement client certificate support with OpenSSL. That's because | 28 // to implement client certificate support with OpenSSL. That's because |
| 30 // only the signing operations used in this use case are implemented here. | 29 // only the signing operations used in this use case are implemented here. |
| 31 // | 30 // |
| 32 // Generally speaking, OpenSSL provides many different ways to sign | 31 // Generally speaking, OpenSSL provides many different ways to sign |
| 33 // digests. This code doesn't support all these cases, only the ones that | 32 // digests. This code doesn't support all these cases, only the ones that |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 308 NULL /* bn_mod_exp */, | 307 NULL /* bn_mod_exp */, |
| 309 RSA_FLAG_OPAQUE, | 308 RSA_FLAG_OPAQUE, |
| 310 NULL /* keygen */, | 309 NULL /* keygen */, |
| 311 }; | 310 }; |
| 312 | 311 |
| 313 // Setup an EVP_PKEY to wrap an existing platform RSA PrivateKey object. | 312 // Setup an EVP_PKEY to wrap an existing platform RSA PrivateKey object. |
| 314 // |private_key| is the JNI reference (local or global) to the object. | 313 // |private_key| is the JNI reference (local or global) to the object. |
| 315 // |legacy_rsa|, if non-NULL, is a pointer to the system OpenSSL RSA object | 314 // |legacy_rsa|, if non-NULL, is a pointer to the system OpenSSL RSA object |
| 316 // backing |private_key|. This parameter is only used for Android < 4.2 to | 315 // backing |private_key|. This parameter is only used for Android < 4.2 to |
| 317 // implement key operations not exposed by the platform. | 316 // implement key operations not exposed by the platform. |
| 318 // |pkey| is the EVP_PKEY to setup as a wrapper. | 317 // Returns a new EVP_PKEY on success, NULL otherwise. |
| 319 // Returns true on success, false otherwise. | |
| 320 // On success, this creates a new global JNI reference to the object | 318 // On success, this creates a new global JNI reference to the object |
| 321 // that is owned by and destroyed with the EVP_PKEY. I.e. caller can | 319 // that is owned by and destroyed with the EVP_PKEY. I.e. caller can |
| 322 // free |private_key| after the call. | 320 // free |private_key| after the call. |
| 323 bool GetRsaPkeyWrapper(jobject private_key, | 321 crypto::ScopedEVP_PKEY GetRsaPkeyWrapper(jobject private_key, |
| 324 AndroidRSA* legacy_rsa, | 322 AndroidRSA* legacy_rsa) { |
| 325 EVP_PKEY* pkey) { | |
| 326 crypto::ScopedRSA rsa( | 323 crypto::ScopedRSA rsa( |
| 327 RSA_new_method(global_boringssl_engine.Get().engine())); | 324 RSA_new_method(global_boringssl_engine.Get().engine())); |
| 328 | 325 |
| 329 ScopedJavaGlobalRef<jobject> global_key; | 326 ScopedJavaGlobalRef<jobject> global_key; |
| 330 global_key.Reset(NULL, private_key); | 327 global_key.Reset(NULL, private_key); |
| 331 if (global_key.is_null()) { | 328 if (global_key.is_null()) { |
| 332 LOG(ERROR) << "Could not create global JNI reference"; | 329 LOG(ERROR) << "Could not create global JNI reference"; |
| 333 return false; | 330 return crypto::ScopedEVP_PKEY(); |
| 334 } | 331 } |
| 335 | 332 |
| 336 std::vector<uint8> modulus; | 333 std::vector<uint8> modulus; |
| 337 if (!GetRSAKeyModulus(private_key, &modulus)) { | 334 if (!GetRSAKeyModulus(private_key, &modulus)) { |
| 338 LOG(ERROR) << "Failed to get private key modulus"; | 335 LOG(ERROR) << "Failed to get private key modulus"; |
| 339 return false; | 336 return crypto::ScopedEVP_PKEY(); |
| 340 } | 337 } |
| 341 | 338 |
| 342 KeyExData* ex_data = new KeyExData; | 339 KeyExData* ex_data = new KeyExData; |
| 343 ex_data->private_key = global_key.Release(); | 340 ex_data->private_key = global_key.Release(); |
| 344 ex_data->legacy_rsa = legacy_rsa; | 341 ex_data->legacy_rsa = legacy_rsa; |
| 345 ex_data->cached_size = VectorBignumSize(modulus); | 342 ex_data->cached_size = VectorBignumSize(modulus); |
| 346 RSA_set_ex_data( | 343 RSA_set_ex_data( |
| 347 rsa.get(), global_boringssl_engine.Get().rsa_ex_index(), ex_data); | 344 rsa.get(), global_boringssl_engine.Get().rsa_ex_index(), ex_data); |
| 348 EVP_PKEY_assign_RSA(pkey, rsa.release()); | 345 |
| 349 return true; | 346 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new()); |
| 347 if (!pkey || | |
| 348 !EVP_PKEY_set1_RSA(pkey.get(), rsa.get())) { | |
|
davidben
2014/09/09 23:07:19
It doesn't really matter because EVP_PKEY_set1_RSA
| |
| 349 return crypto::ScopedEVP_PKEY(); | |
| 350 } | |
| 351 return pkey.Pass(); | |
| 350 } | 352 } |
| 351 | 353 |
| 352 // On Android < 4.2, the libkeystore.so ENGINE uses CRYPTO_EX_DATA and is not | 354 // On Android < 4.2, the libkeystore.so ENGINE uses CRYPTO_EX_DATA and is not |
| 353 // added to the global engine list. If all references to it are dropped, OpenSSL | 355 // added to the global engine list. If all references to it are dropped, OpenSSL |
| 354 // will dlclose the module, leaving a dangling function pointer in the RSA | 356 // will dlclose the module, leaving a dangling function pointer in the RSA |
| 355 // CRYPTO_EX_DATA class. To work around this, leak an extra reference to the | 357 // CRYPTO_EX_DATA class. To work around this, leak an extra reference to the |
| 356 // ENGINE we extract in GetRsaLegacyKey. | 358 // ENGINE we extract in GetRsaLegacyKey. |
| 357 // | 359 // |
| 358 // In 4.2, this change avoids the problem: | 360 // In 4.2, this change avoids the problem: |
| 359 // https://android.googlesource.com/platform/libcore/+/106a8928fb4249f2f3d4dba1d ddbe73ca5cb3d61 | 361 // https://android.googlesource.com/platform/libcore/+/106a8928fb4249f2f3d4dba1d ddbe73ca5cb3d61 |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 383 static base::LazyInstance<KeystoreEngineWorkaround>::Leaky s_instance = | 385 static base::LazyInstance<KeystoreEngineWorkaround>::Leaky s_instance = |
| 384 LAZY_INSTANCE_INITIALIZER; | 386 LAZY_INSTANCE_INITIALIZER; |
| 385 s_instance.Get().LeakEngine(private_key); | 387 s_instance.Get().LeakEngine(private_key); |
| 386 } | 388 } |
| 387 | 389 |
| 388 // Setup an EVP_PKEY to wrap an existing platform RSA PrivateKey object | 390 // Setup an EVP_PKEY to wrap an existing platform RSA PrivateKey object |
| 389 // for Android 4.0 to 4.1.x. Must only be used on Android < 4.2. | 391 // for Android 4.0 to 4.1.x. Must only be used on Android < 4.2. |
| 390 // |private_key| is a JNI reference (local or global) to the object. | 392 // |private_key| is a JNI reference (local or global) to the object. |
| 391 // |pkey| is the EVP_PKEY to setup as a wrapper. | 393 // |pkey| is the EVP_PKEY to setup as a wrapper. |
| 392 // Returns true on success, false otherwise. | 394 // Returns true on success, false otherwise. |
| 393 EVP_PKEY* GetRsaLegacyKey(jobject private_key) { | 395 crypto::ScopedEVP_PKEY GetRsaLegacyKey(jobject private_key) { |
| 394 AndroidEVP_PKEY* sys_pkey = | 396 AndroidEVP_PKEY* sys_pkey = |
| 395 GetOpenSSLSystemHandleForPrivateKey(private_key); | 397 GetOpenSSLSystemHandleForPrivateKey(private_key); |
| 396 if (sys_pkey != NULL) { | 398 if (sys_pkey != NULL) { |
| 397 if (sys_pkey->type != ANDROID_EVP_PKEY_RSA) { | 399 if (sys_pkey->type != ANDROID_EVP_PKEY_RSA) { |
| 398 LOG(ERROR) << "Private key has wrong type!"; | 400 LOG(ERROR) << "Private key has wrong type!"; |
| 399 return NULL; | 401 return crypto::ScopedEVP_PKEY(); |
| 400 } | 402 } |
| 401 | 403 |
| 402 AndroidRSA* sys_rsa = sys_pkey->pkey.rsa; | 404 AndroidRSA* sys_rsa = sys_pkey->pkey.rsa; |
| 403 if (sys_rsa->engine) { | 405 if (sys_rsa->engine) { |
| 404 // |private_key| may not have an engine if the PrivateKey did not come | 406 // |private_key| may not have an engine if the PrivateKey did not come |
| 405 // from the key store, such as in unit tests. | 407 // from the key store, such as in unit tests. |
| 406 if (strcmp(sys_rsa->engine->id, "keystore") == 0) { | 408 if (strcmp(sys_rsa->engine->id, "keystore") == 0) { |
| 407 LeakEngine(private_key); | 409 LeakEngine(private_key); |
| 408 } else { | 410 } else { |
| 409 NOTREACHED(); | 411 NOTREACHED(); |
| 410 } | 412 } |
| 411 } | 413 } |
| 412 | 414 |
| 413 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new()); | 415 return GetRsaPkeyWrapper(private_key, sys_rsa); |
| 414 if (!GetRsaPkeyWrapper(private_key, sys_rsa, pkey.get())) | |
| 415 return NULL; | |
| 416 return pkey.release(); | |
| 417 } | 416 } |
| 418 | 417 |
| 419 // GetOpenSSLSystemHandleForPrivateKey() will fail on Android 4.0.3 and | 418 // GetOpenSSLSystemHandleForPrivateKey() will fail on Android 4.0.3 and |
| 420 // earlier. However, it is possible to get the key content with | 419 // earlier. However, it is possible to get the key content with |
| 421 // PrivateKey.getEncoded() on these platforms. Note that this method may | 420 // PrivateKey.getEncoded() on these platforms. Note that this method may |
| 422 // return NULL on 4.0.4 and later. | 421 // return NULL on 4.0.4 and later. |
| 423 std::vector<uint8> encoded; | 422 std::vector<uint8> encoded; |
| 424 if (!GetPrivateKeyEncodedBytes(private_key, &encoded)) { | 423 if (!GetPrivateKeyEncodedBytes(private_key, &encoded)) { |
| 425 LOG(ERROR) << "Can't get private key data!"; | 424 LOG(ERROR) << "Can't get private key data!"; |
| 426 return NULL; | 425 return crypto::ScopedEVP_PKEY(); |
| 427 } | 426 } |
| 428 const unsigned char* p = | 427 const unsigned char* p = |
| 429 reinterpret_cast<const unsigned char*>(&encoded[0]); | 428 reinterpret_cast<const unsigned char*>(&encoded[0]); |
| 430 int len = static_cast<int>(encoded.size()); | 429 int len = static_cast<int>(encoded.size()); |
| 431 EVP_PKEY* pkey = d2i_AutoPrivateKey(NULL, &p, len); | 430 crypto::ScopedEVP_PKEY pkey(d2i_AutoPrivateKey(NULL, &p, len)); |
| 432 if (pkey == NULL) { | 431 if (!pkey) { |
| 433 LOG(ERROR) << "Can't convert private key data!"; | 432 LOG(ERROR) << "Can't convert private key data!"; |
| 434 return NULL; | 433 return crypto::ScopedEVP_PKEY(); |
| 435 } | 434 } |
| 436 return pkey; | 435 return pkey.Pass(); |
| 437 } | 436 } |
| 438 | 437 |
| 439 // Custom ECDSA_METHOD that uses the platform APIs. | 438 // Custom ECDSA_METHOD that uses the platform APIs. |
| 440 // Note that for now, only signing through ECDSA_sign() is really supported. | 439 // Note that for now, only signing through ECDSA_sign() is really supported. |
| 441 // all other method pointers are either stubs returning errors, or no-ops. | 440 // all other method pointers are either stubs returning errors, or no-ops. |
| 442 | 441 |
| 443 jobject EcKeyGetKey(const EC_KEY* ec_key) { | 442 jobject EcKeyGetKey(const EC_KEY* ec_key) { |
| 444 KeyExData* ex_data = reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data( | 443 KeyExData* ex_data = reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data( |
| 445 ec_key, global_boringssl_engine.Get().ec_key_ex_index())); | 444 ec_key, global_boringssl_engine.Get().ec_key_ex_index())); |
| 446 return ex_data->private_key; | 445 return ex_data->private_key; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 492 const uint8_t* sig, | 491 const uint8_t* sig, |
| 493 size_t sig_len, | 492 size_t sig_len, |
| 494 EC_KEY* ec_key) { | 493 EC_KEY* ec_key) { |
| 495 NOTIMPLEMENTED(); | 494 NOTIMPLEMENTED(); |
| 496 OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ECDSA_R_NOT_IMPLEMENTED); | 495 OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ECDSA_R_NOT_IMPLEMENTED); |
| 497 return 0; | 496 return 0; |
| 498 } | 497 } |
| 499 | 498 |
| 500 // Setup an EVP_PKEY to wrap an existing platform PrivateKey object. | 499 // Setup an EVP_PKEY to wrap an existing platform PrivateKey object. |
| 501 // |private_key| is the JNI reference (local or global) to the object. | 500 // |private_key| is the JNI reference (local or global) to the object. |
| 502 // |pkey| is the EVP_PKEY to setup as a wrapper. | 501 // Returns a new EVP_PKEY on success, NULL otherwise. |
| 503 // Returns true on success, false otherwise. | |
| 504 // On success, this creates a global JNI reference to the object that | 502 // On success, this creates a global JNI reference to the object that |
| 505 // is owned by and destroyed with the EVP_PKEY. I.e. the caller shall | 503 // is owned by and destroyed with the EVP_PKEY. I.e. the caller shall |
| 506 // always free |private_key| after the call. | 504 // always free |private_key| after the call. |
| 507 bool GetEcdsaPkeyWrapper(jobject private_key, EVP_PKEY* pkey) { | 505 crypto::ScopedEVP_PKEY GetEcdsaPkeyWrapper(jobject private_key) { |
| 508 crypto::ScopedEC_KEY ec_key( | 506 crypto::ScopedEC_KEY ec_key( |
| 509 EC_KEY_new_method(global_boringssl_engine.Get().engine())); | 507 EC_KEY_new_method(global_boringssl_engine.Get().engine())); |
| 510 | 508 |
| 511 ScopedJavaGlobalRef<jobject> global_key; | 509 ScopedJavaGlobalRef<jobject> global_key; |
| 512 global_key.Reset(NULL, private_key); | 510 global_key.Reset(NULL, private_key); |
| 513 if (global_key.is_null()) { | 511 if (global_key.is_null()) { |
| 514 LOG(ERROR) << "Can't create global JNI reference"; | 512 LOG(ERROR) << "Can't create global JNI reference"; |
| 515 return false; | 513 return crypto::ScopedEVP_PKEY(); |
| 516 } | 514 } |
| 517 | 515 |
| 518 std::vector<uint8> order; | 516 std::vector<uint8> order; |
| 519 if (!GetECKeyOrder(private_key, &order)) { | 517 if (!GetECKeyOrder(private_key, &order)) { |
| 520 LOG(ERROR) << "Can't extract order parameter from EC private key"; | 518 LOG(ERROR) << "Can't extract order parameter from EC private key"; |
| 521 return false; | 519 return crypto::ScopedEVP_PKEY(); |
| 522 } | 520 } |
| 523 | 521 |
| 524 KeyExData* ex_data = new KeyExData; | 522 KeyExData* ex_data = new KeyExData; |
| 525 ex_data->private_key = global_key.Release(); | 523 ex_data->private_key = global_key.Release(); |
| 526 ex_data->legacy_rsa = NULL; | 524 ex_data->legacy_rsa = NULL; |
| 527 ex_data->cached_size = VectorBignumSize(order); | 525 ex_data->cached_size = VectorBignumSize(order); |
| 528 | 526 |
| 529 EC_KEY_set_ex_data( | 527 EC_KEY_set_ex_data( |
| 530 ec_key.get(), global_boringssl_engine.Get().ec_key_ex_index(), ex_data); | 528 ec_key.get(), global_boringssl_engine.Get().ec_key_ex_index(), ex_data); |
| 531 | 529 |
| 532 EVP_PKEY_assign_EC_KEY(pkey, ec_key.release()); | 530 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new()); |
| 533 return true; | 531 if (!pkey || |
| 532 !EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get())) { | |
| 533 return crypto::ScopedEVP_PKEY(); | |
| 534 } | |
| 535 return pkey.Pass(); | |
| 534 } | 536 } |
| 535 | 537 |
| 536 const ECDSA_METHOD android_ecdsa_method = { | 538 const ECDSA_METHOD android_ecdsa_method = { |
| 537 { | 539 { |
| 538 0 /* references */, | 540 0 /* references */, |
| 539 1 /* is_static */ | 541 1 /* is_static */ |
| 540 } /* common */, | 542 } /* common */, |
| 541 NULL /* app_data */, | 543 NULL /* app_data */, |
| 542 | 544 |
| 543 NULL /* init */, | 545 NULL /* init */, |
| 544 NULL /* finish */, | 546 NULL /* finish */, |
| 545 EcdsaMethodGroupOrderSize, | 547 EcdsaMethodGroupOrderSize, |
| 546 EcdsaMethodSign, | 548 EcdsaMethodSign, |
| 547 EcdsaMethodVerify, | 549 EcdsaMethodVerify, |
| 548 ECDSA_FLAG_OPAQUE, | 550 ECDSA_FLAG_OPAQUE, |
| 549 }; | 551 }; |
| 550 | 552 |
| 551 } // namespace | 553 } // namespace |
| 552 | 554 |
| 553 EVP_PKEY* GetOpenSSLPrivateKeyWrapper(jobject private_key) { | 555 crypto::ScopedEVP_PKEY GetOpenSSLPrivateKeyWrapper(jobject private_key) { |
| 554 // Create new empty EVP_PKEY instance. | 556 const int kAndroid42ApiLevel = 17; |
| 555 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new()); | |
| 556 if (!pkey.get()) | |
| 557 return NULL; | |
| 558 | 557 |
| 559 // Create sub key type, depending on private key's algorithm type. | 558 // Create sub key type, depending on private key's algorithm type. |
| 560 PrivateKeyType key_type = GetPrivateKeyType(private_key); | 559 PrivateKeyType key_type = GetPrivateKeyType(private_key); |
| 561 switch (key_type) { | 560 switch (key_type) { |
| 562 case PRIVATE_KEY_TYPE_RSA: | 561 case PRIVATE_KEY_TYPE_RSA: |
| 563 { | 562 // Route around platform bug: if Android < 4.2, then |
| 564 // Route around platform bug: if Android < 4.2, then | 563 // base::android::RawSignDigestWithPrivateKey() cannot work, so |
| 565 // base::android::RawSignDigestWithPrivateKey() cannot work, so | 564 // instead, obtain a raw EVP_PKEY* to the system object |
| 566 // instead, obtain a raw EVP_PKEY* to the system object | 565 // backing this PrivateKey object. |
| 567 // backing this PrivateKey object. | 566 if (base::android::BuildInfo::GetInstance()->sdk_int() < |
| 568 const int kAndroid42ApiLevel = 17; | 567 kAndroid42ApiLevel) { |
| 569 if (base::android::BuildInfo::GetInstance()->sdk_int() < | 568 return GetRsaLegacyKey(private_key); |
| 570 kAndroid42ApiLevel) { | 569 } else { |
| 571 EVP_PKEY* legacy_key = GetRsaLegacyKey(private_key); | 570 // Running on Android 4.2. |
| 572 if (legacy_key == NULL) | 571 return GetRsaPkeyWrapper(private_key, NULL); |
| 573 return NULL; | |
| 574 pkey.reset(legacy_key); | |
| 575 } else { | |
| 576 // Running on Android 4.2. | |
| 577 if (!GetRsaPkeyWrapper(private_key, NULL, pkey.get())) | |
| 578 return NULL; | |
| 579 } | |
| 580 } | 572 } |
| 581 break; | |
| 582 case PRIVATE_KEY_TYPE_ECDSA: | 573 case PRIVATE_KEY_TYPE_ECDSA: |
| 583 if (!GetEcdsaPkeyWrapper(private_key, pkey.get())) | 574 return GetEcdsaPkeyWrapper(private_key); |
| 584 return NULL; | |
| 585 break; | |
| 586 default: | 575 default: |
| 587 LOG(WARNING) | 576 LOG(WARNING) |
| 588 << "GetOpenSSLPrivateKeyWrapper() called with invalid key type"; | 577 << "GetOpenSSLPrivateKeyWrapper() called with invalid key type"; |
| 589 return NULL; | 578 return crypto::ScopedEVP_PKEY(); |
| 590 } | 579 } |
| 591 return pkey.release(); | |
| 592 } | 580 } |
| 593 | 581 |
| 594 } // namespace android | 582 } // namespace android |
| 595 } // namespace net | 583 } // namespace net |
| OLD | NEW |