Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(37)

Side by Side Diff: net/android/keystore_openssl.cc

Issue 833243008: Update from https://crrev.com/311145 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « mojo/edk/test/multiprocess_test_helper.cc ('k') | net/http/transport_security_state_static.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « mojo/edk/test/multiprocess_test_helper.cc ('k') | net/http/transport_security_state_static.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698