| 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 <openssl/bn.h> | 5 #include <openssl/bn.h> |
| 6 #include <openssl/dsa.h> | 6 #include <openssl/dsa.h> |
| 7 #include <openssl/ecdsa.h> | 7 #include <openssl/ecdsa.h> |
| 8 #include <openssl/err.h> | 8 #include <openssl/err.h> |
| 9 #include <openssl/evp.h> | 9 #include <openssl/evp.h> |
| 10 #include <openssl/pem.h> | 10 #include <openssl/pem.h> |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 // possible to create a custom EVP_PKEY that uses | 44 // possible to create a custom EVP_PKEY that uses |
| 45 // RawSignDigestWithPrivateKey() internally to perform RSA/DSA/ECDSA | 45 // RawSignDigestWithPrivateKey() internally to perform RSA/DSA/ECDSA |
| 46 // signing, as invoked by the OpenSSL code at | 46 // signing, as invoked by the OpenSSL code at |
| 47 // openssl/ssl/s3_clnt.c:ssl3_send_client_verify(). | 47 // openssl/ssl/s3_clnt.c:ssl3_send_client_verify(). |
| 48 // | 48 // |
| 49 // For more details, read the comments in AndroidKeyStore.java. | 49 // For more details, read the comments in AndroidKeyStore.java. |
| 50 // | 50 // |
| 51 // Finally, it also checks that using the EVP_PKEY generated with | 51 // Finally, it also checks that using the EVP_PKEY generated with |
| 52 // GetOpenSSLPrivateKeyWrapper() works correctly. | 52 // GetOpenSSLPrivateKeyWrapper() works correctly. |
| 53 | 53 |
| 54 using base::android::JavaRef; |
| 55 |
| 54 namespace net { | 56 namespace net { |
| 55 namespace android { | 57 namespace android { |
| 56 | 58 |
| 57 namespace { | 59 namespace { |
| 58 | 60 |
| 59 typedef base::android::ScopedJavaLocalRef<jobject> ScopedJava; | 61 typedef base::android::ScopedJavaLocalRef<jobject> ScopedJava; |
| 60 | 62 |
| 61 // Returns true if running on an Android version older than 4.2 | 63 // Returns true if running on an Android version older than 4.2 |
| 62 bool IsOnAndroidOlderThan_4_2(void) { | 64 bool IsOnAndroidOlderThan_4_2(void) { |
| 63 const int kAndroid42ApiLevel = 17; | 65 const int kAndroid42ApiLevel = 17; |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 348 return true; | 350 return true; |
| 349 } | 351 } |
| 350 | 352 |
| 351 // Sign a message with our platform API. | 353 // Sign a message with our platform API. |
| 352 // | 354 // |
| 353 // |android_key| is a JNI reference to the platform PrivateKey object. | 355 // |android_key| is a JNI reference to the platform PrivateKey object. |
| 354 // |openssl_key| is a pointer to an OpenSSL key object for the exact | 356 // |openssl_key| is a pointer to an OpenSSL key object for the exact |
| 355 // same key content. | 357 // same key content. |
| 356 // |message| is a message. | 358 // |message| is a message. |
| 357 // |result| will receive the result. | 359 // |result| will receive the result. |
| 358 void DoKeySigning(jobject android_key, | 360 void DoKeySigning(const JavaRef<jobject>& android_key, |
| 359 EVP_PKEY* openssl_key, | 361 EVP_PKEY* openssl_key, |
| 360 const base::StringPiece& message, | 362 const base::StringPiece& message, |
| 361 std::string* result) { | 363 std::string* result) { |
| 362 // First, get the platform signature. | 364 // First, get the platform signature. |
| 363 std::vector<uint8_t> android_signature; | 365 std::vector<uint8_t> android_signature; |
| 364 ASSERT_TRUE( | 366 ASSERT_TRUE( |
| 365 RawSignDigestWithPrivateKey(android_key, | 367 RawSignDigestWithPrivateKey(android_key, |
| 366 message, | 368 message, |
| 367 &android_signature)); | 369 &android_signature)); |
| 368 | 370 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 406 std::string pkcs8_data; | 408 std::string pkcs8_data; |
| 407 ASSERT_TRUE(GetPrivateKeyPkcs8Bytes(pkey, &pkcs8_data)); | 409 ASSERT_TRUE(GetPrivateKeyPkcs8Bytes(pkey, &pkcs8_data)); |
| 408 | 410 |
| 409 // Create platform PrivateKey object from it. | 411 // Create platform PrivateKey object from it. |
| 410 ScopedJava key_java = GetPKCS8PrivateKeyJava(PRIVATE_KEY_TYPE_RSA, | 412 ScopedJava key_java = GetPKCS8PrivateKeyJava(PRIVATE_KEY_TYPE_RSA, |
| 411 pkcs8_data); | 413 pkcs8_data); |
| 412 ASSERT_FALSE(key_java.is_null()); | 414 ASSERT_FALSE(key_java.is_null()); |
| 413 | 415 |
| 414 // Retrieve the corresponding modulus through JNI | 416 // Retrieve the corresponding modulus through JNI |
| 415 std::vector<uint8_t> modulus_java; | 417 std::vector<uint8_t> modulus_java; |
| 416 ASSERT_TRUE(GetRSAKeyModulus(key_java.obj(), &modulus_java)); | 418 ASSERT_TRUE(GetRSAKeyModulus(key_java, &modulus_java)); |
| 417 | 419 |
| 418 // Create an OpenSSL BIGNUM from it. | 420 // Create an OpenSSL BIGNUM from it. |
| 419 crypto::ScopedBIGNUM bn( | 421 crypto::ScopedBIGNUM bn( |
| 420 BN_bin2bn(reinterpret_cast<const unsigned char*>(&modulus_java[0]), | 422 BN_bin2bn(reinterpret_cast<const unsigned char*>(&modulus_java[0]), |
| 421 static_cast<int>(modulus_java.size()), | 423 static_cast<int>(modulus_java.size()), |
| 422 NULL)); | 424 NULL)); |
| 423 ASSERT_TRUE(bn.get()); | 425 ASSERT_TRUE(bn.get()); |
| 424 | 426 |
| 425 // Compare it to the one in the RSA key, they must be identical. | 427 // Compare it to the one in the RSA key, they must be identical. |
| 426 crypto::ScopedRSA rsa(EVP_PKEY_get1_RSA(pkey.get())); | 428 crypto::ScopedRSA rsa(EVP_PKEY_get1_RSA(pkey.get())); |
| 427 ASSERT_TRUE(rsa.get()) << GetOpenSSLErrorString(); | 429 ASSERT_TRUE(rsa.get()) << GetOpenSSLErrorString(); |
| 428 | 430 |
| 429 ASSERT_EQ(0, BN_cmp(bn.get(), rsa.get()->n)); | 431 ASSERT_EQ(0, BN_cmp(bn.get(), rsa.get()->n)); |
| 430 } | 432 } |
| 431 | 433 |
| 432 TEST(AndroidKeyStore,GetPrivateKeyTypeRSA) { | 434 TEST(AndroidKeyStore,GetPrivateKeyTypeRSA) { |
| 433 crypto::OpenSSLErrStackTracer err_trace(FROM_HERE); | 435 crypto::OpenSSLErrStackTracer err_trace(FROM_HERE); |
| 434 | 436 |
| 435 ScopedJava rsa_key = GetRSATestKeyJava(); | 437 ScopedJava rsa_key = GetRSATestKeyJava(); |
| 436 ASSERT_FALSE(rsa_key.is_null()); | 438 ASSERT_FALSE(rsa_key.is_null()); |
| 437 EXPECT_EQ(PRIVATE_KEY_TYPE_RSA, | 439 EXPECT_EQ(PRIVATE_KEY_TYPE_RSA, GetPrivateKeyType(rsa_key)); |
| 438 GetPrivateKeyType(rsa_key.obj())); | |
| 439 } | 440 } |
| 440 | 441 |
| 441 TEST(AndroidKeyStore,SignWithPrivateKeyRSA) { | 442 TEST(AndroidKeyStore,SignWithPrivateKeyRSA) { |
| 442 ScopedJava rsa_key = GetRSATestKeyJava(); | 443 ScopedJava rsa_key = GetRSATestKeyJava(); |
| 443 ASSERT_FALSE(rsa_key.is_null()); | 444 ASSERT_FALSE(rsa_key.is_null()); |
| 444 | 445 |
| 445 if (IsOnAndroidOlderThan_4_2()) { | 446 if (IsOnAndroidOlderThan_4_2()) { |
| 446 LOG(INFO) << "This test can't run on Android < 4.2"; | 447 LOG(INFO) << "This test can't run on Android < 4.2"; |
| 447 return; | 448 return; |
| 448 } | 449 } |
| 449 | 450 |
| 450 crypto::ScopedEVP_PKEY openssl_key(ImportPrivateKeyFile(kTestRsaKeyFile)); | 451 crypto::ScopedEVP_PKEY openssl_key(ImportPrivateKeyFile(kTestRsaKeyFile)); |
| 451 ASSERT_TRUE(openssl_key.get()); | 452 ASSERT_TRUE(openssl_key.get()); |
| 452 | 453 |
| 453 std::string message = kTestRsaHash; | 454 std::string message = kTestRsaHash; |
| 454 ASSERT_EQ(36U, message.size()); | 455 ASSERT_EQ(36U, message.size()); |
| 455 | 456 |
| 456 std::string signature; | 457 std::string signature; |
| 457 DoKeySigning(rsa_key.obj(), openssl_key.get(), message, &signature); | 458 DoKeySigning(rsa_key, openssl_key.get(), message, &signature); |
| 458 ASSERT_TRUE( | 459 ASSERT_TRUE( |
| 459 CompareSignatureWithOpenSSL(message, signature, openssl_key.get())); | 460 CompareSignatureWithOpenSSL(message, signature, openssl_key.get())); |
| 460 // All good. | 461 // All good. |
| 461 } | 462 } |
| 462 | 463 |
| 463 TEST(AndroidKeyStore,SignWithWrapperKeyRSA) { | 464 TEST(AndroidKeyStore,SignWithWrapperKeyRSA) { |
| 464 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 465 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 465 | 466 |
| 466 ScopedJava rsa_key = GetRSATestKeyJava(); | 467 ScopedJava rsa_key = GetRSATestKeyJava(); |
| 467 ASSERT_FALSE(rsa_key.is_null()); | 468 ASSERT_FALSE(rsa_key.is_null()); |
| 468 | 469 |
| 469 crypto::ScopedEVP_PKEY wrapper_key( | 470 crypto::ScopedEVP_PKEY wrapper_key(GetOpenSSLPrivateKeyWrapper(rsa_key)); |
| 470 GetOpenSSLPrivateKeyWrapper(rsa_key.obj())); | |
| 471 ASSERT_TRUE(wrapper_key.get() != NULL); | 471 ASSERT_TRUE(wrapper_key.get() != NULL); |
| 472 | 472 |
| 473 crypto::ScopedEVP_PKEY openssl_key(ImportPrivateKeyFile(kTestRsaKeyFile)); | 473 crypto::ScopedEVP_PKEY openssl_key(ImportPrivateKeyFile(kTestRsaKeyFile)); |
| 474 ASSERT_TRUE(openssl_key.get()); | 474 ASSERT_TRUE(openssl_key.get()); |
| 475 | 475 |
| 476 // Check that RSA_size() works properly on the wrapper key. | 476 // Check that RSA_size() works properly on the wrapper key. |
| 477 EXPECT_EQ(EVP_PKEY_size(openssl_key.get()), | 477 EXPECT_EQ(EVP_PKEY_size(openssl_key.get()), |
| 478 EVP_PKEY_size(wrapper_key.get())); | 478 EVP_PKEY_size(wrapper_key.get())); |
| 479 | 479 |
| 480 // Message size must be 36 for RSA_sign(NID_md5_sha1,...) to return | 480 // Message size must be 36 for RSA_sign(NID_md5_sha1,...) to return |
| 481 // without an error. | 481 // without an error. |
| 482 std::string message = kTestRsaHash; | 482 std::string message = kTestRsaHash; |
| 483 ASSERT_EQ(36U, message.size()); | 483 ASSERT_EQ(36U, message.size()); |
| 484 | 484 |
| 485 std::string signature; | 485 std::string signature; |
| 486 DoKeySigningWithWrapper(wrapper_key.get(), | 486 DoKeySigningWithWrapper(wrapper_key.get(), |
| 487 openssl_key.get(), | 487 openssl_key.get(), |
| 488 message, | 488 message, |
| 489 &signature); | 489 &signature); |
| 490 ASSERT_TRUE( | 490 ASSERT_TRUE( |
| 491 CompareSignatureWithOpenSSL(message, signature, openssl_key.get())); | 491 CompareSignatureWithOpenSSL(message, signature, openssl_key.get())); |
| 492 } | 492 } |
| 493 | 493 |
| 494 TEST(AndroidKeyStore,GetPrivateKeyTypeECDSA) { | 494 TEST(AndroidKeyStore,GetPrivateKeyTypeECDSA) { |
| 495 crypto::OpenSSLErrStackTracer err_trace(FROM_HERE); | 495 crypto::OpenSSLErrStackTracer err_trace(FROM_HERE); |
| 496 | 496 |
| 497 ScopedJava ecdsa_key = GetECDSATestKeyJava(); | 497 ScopedJava ecdsa_key = GetECDSATestKeyJava(); |
| 498 ASSERT_FALSE(ecdsa_key.is_null()); | 498 ASSERT_FALSE(ecdsa_key.is_null()); |
| 499 EXPECT_EQ(PRIVATE_KEY_TYPE_ECDSA, | 499 EXPECT_EQ(PRIVATE_KEY_TYPE_ECDSA, GetPrivateKeyType(ecdsa_key)); |
| 500 GetPrivateKeyType(ecdsa_key.obj())); | |
| 501 } | 500 } |
| 502 | 501 |
| 503 TEST(AndroidKeyStore,SignWithPrivateKeyECDSA) { | 502 TEST(AndroidKeyStore,SignWithPrivateKeyECDSA) { |
| 504 ScopedJava ecdsa_key = GetECDSATestKeyJava(); | 503 ScopedJava ecdsa_key = GetECDSATestKeyJava(); |
| 505 ASSERT_FALSE(ecdsa_key.is_null()); | 504 ASSERT_FALSE(ecdsa_key.is_null()); |
| 506 | 505 |
| 507 crypto::ScopedEVP_PKEY openssl_key(ImportPrivateKeyFile(kTestEcdsaKeyFile)); | 506 crypto::ScopedEVP_PKEY openssl_key(ImportPrivateKeyFile(kTestEcdsaKeyFile)); |
| 508 ASSERT_TRUE(openssl_key.get()); | 507 ASSERT_TRUE(openssl_key.get()); |
| 509 | 508 |
| 510 std::string message = kTestEcdsaHash; | 509 std::string message = kTestEcdsaHash; |
| 511 std::string signature; | 510 std::string signature; |
| 512 DoKeySigning(ecdsa_key.obj(), openssl_key.get(), message, &signature); | 511 DoKeySigning(ecdsa_key, openssl_key.get(), message, &signature); |
| 513 ASSERT_TRUE(VerifyTestECDSASignature(message, signature)); | 512 ASSERT_TRUE(VerifyTestECDSASignature(message, signature)); |
| 514 } | 513 } |
| 515 | 514 |
| 516 TEST(AndroidKeyStore, SignWithWrapperKeyECDSA) { | 515 TEST(AndroidKeyStore, SignWithWrapperKeyECDSA) { |
| 517 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 516 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 518 | 517 |
| 519 ScopedJava ecdsa_key = GetECDSATestKeyJava(); | 518 ScopedJava ecdsa_key = GetECDSATestKeyJava(); |
| 520 ASSERT_FALSE(ecdsa_key.is_null()); | 519 ASSERT_FALSE(ecdsa_key.is_null()); |
| 521 | 520 |
| 522 crypto::ScopedEVP_PKEY wrapper_key( | 521 crypto::ScopedEVP_PKEY wrapper_key(GetOpenSSLPrivateKeyWrapper(ecdsa_key)); |
| 523 GetOpenSSLPrivateKeyWrapper(ecdsa_key.obj())); | |
| 524 ASSERT_TRUE(wrapper_key.get()); | 522 ASSERT_TRUE(wrapper_key.get()); |
| 525 | 523 |
| 526 crypto::ScopedEVP_PKEY openssl_key(ImportPrivateKeyFile(kTestEcdsaKeyFile)); | 524 crypto::ScopedEVP_PKEY openssl_key(ImportPrivateKeyFile(kTestEcdsaKeyFile)); |
| 527 ASSERT_TRUE(openssl_key.get()); | 525 ASSERT_TRUE(openssl_key.get()); |
| 528 | 526 |
| 529 // Check that ECDSA size works correctly on the wrapper. | 527 // Check that ECDSA size works correctly on the wrapper. |
| 530 EXPECT_EQ(EVP_PKEY_size(openssl_key.get()), | 528 EXPECT_EQ(EVP_PKEY_size(openssl_key.get()), |
| 531 EVP_PKEY_size(wrapper_key.get())); | 529 EVP_PKEY_size(wrapper_key.get())); |
| 532 | 530 |
| 533 std::string message = kTestEcdsaHash; | 531 std::string message = kTestEcdsaHash; |
| 534 std::string signature; | 532 std::string signature; |
| 535 DoKeySigningWithWrapper(wrapper_key.get(), | 533 DoKeySigningWithWrapper(wrapper_key.get(), |
| 536 openssl_key.get(), | 534 openssl_key.get(), |
| 537 message, | 535 message, |
| 538 &signature); | 536 &signature); |
| 539 ASSERT_TRUE(VerifyTestECDSASignature(message, signature)); | 537 ASSERT_TRUE(VerifyTestECDSASignature(message, signature)); |
| 540 } | 538 } |
| 541 | 539 |
| 542 } // namespace android | 540 } // namespace android |
| 543 } // namespace net | 541 } // namespace net |
| OLD | NEW |