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 |