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 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 const char kTestRsaHash[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | 198 const char kTestRsaHash[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
199 | 199 |
200 // Retrieve a JNI local ref for our test RSA key. | 200 // Retrieve a JNI local ref for our test RSA key. |
201 ScopedJava GetRSATestKeyJava() { | 201 ScopedJava GetRSATestKeyJava() { |
202 std::string key; | 202 std::string key; |
203 if (!ImportPrivateKeyFileAsPkcs8(kTestRsaKeyFile, &key)) | 203 if (!ImportPrivateKeyFileAsPkcs8(kTestRsaKeyFile, &key)) |
204 return ScopedJava(); | 204 return ScopedJava(); |
205 return GetPKCS8PrivateKeyJava(PRIVATE_KEY_TYPE_RSA, key); | 205 return GetPKCS8PrivateKeyJava(PRIVATE_KEY_TYPE_RSA, key); |
206 } | 206 } |
207 | 207 |
| 208 const char kTestDsaKeyFile[] = "android-test-key-dsa.pem"; |
| 209 const char kTestDsaPublicKeyFile[] = "android-test-key-dsa-public.pem"; |
| 210 |
| 211 // The DSA test hash must be 20 bytes exactly. |
| 212 const char kTestDsaHash[] = "0123456789ABCDEFGHIJ"; |
| 213 |
| 214 // Retrieve a JNI local ref for our test DSA key. |
| 215 ScopedJava GetDSATestKeyJava() { |
| 216 std::string key; |
| 217 if (!ImportPrivateKeyFileAsPkcs8(kTestDsaKeyFile, &key)) |
| 218 return ScopedJava(); |
| 219 return GetPKCS8PrivateKeyJava(PRIVATE_KEY_TYPE_DSA, key); |
| 220 } |
| 221 |
| 222 // Call this function to verify that one message signed with our |
| 223 // test DSA private key is correct. Since DSA signing introduces |
| 224 // random elements in the signature, it is not possible to compare |
| 225 // signature bits directly. However, one can use the public key |
| 226 // to do the check. |
| 227 bool VerifyTestDSASignature(const base::StringPiece& message, |
| 228 const base::StringPiece& signature) { |
| 229 crypto::ScopedEVP_PKEY pkey(ImportPublicKeyFile(kTestDsaPublicKeyFile)); |
| 230 if (!pkey.get()) |
| 231 return false; |
| 232 |
| 233 crypto::ScopedDSA pub_key(EVP_PKEY_get1_DSA(pkey.get())); |
| 234 if (!pub_key.get()) { |
| 235 LOG(ERROR) << "Could not get DSA public key: " |
| 236 << GetOpenSSLErrorString(); |
| 237 return false; |
| 238 } |
| 239 |
| 240 const unsigned char* digest = |
| 241 reinterpret_cast<const unsigned char*>(message.data()); |
| 242 int digest_len = static_cast<int>(message.size()); |
| 243 const unsigned char* sigbuf = |
| 244 reinterpret_cast<const unsigned char*>(signature.data()); |
| 245 int siglen = static_cast<int>(signature.size()); |
| 246 |
| 247 int ret = DSA_verify( |
| 248 0, digest, digest_len, sigbuf, siglen, pub_key.get()); |
| 249 if (ret != 1) { |
| 250 LOG(ERROR) << "DSA_verify() failed: " << GetOpenSSLErrorString(); |
| 251 return false; |
| 252 } |
| 253 return true; |
| 254 } |
| 255 |
208 const char kTestEcdsaKeyFile[] = "android-test-key-ecdsa.pem"; | 256 const char kTestEcdsaKeyFile[] = "android-test-key-ecdsa.pem"; |
209 const char kTestEcdsaPublicKeyFile[] = "android-test-key-ecdsa-public.pem"; | 257 const char kTestEcdsaPublicKeyFile[] = "android-test-key-ecdsa-public.pem"; |
210 | 258 |
211 // The test hash for ECDSA keys must be 20 bytes exactly. | 259 // The test hash for ECDSA keys must be 20 bytes exactly. |
212 const char kTestEcdsaHash[] = "0123456789ABCDEFGHIJ"; | 260 const char kTestEcdsaHash[] = "0123456789ABCDEFGHIJ"; |
213 | 261 |
214 // Retrieve a JNI local ref for our test ECDSA key. | 262 // Retrieve a JNI local ref for our test ECDSA key. |
215 ScopedJava GetECDSATestKeyJava() { | 263 ScopedJava GetECDSATestKeyJava() { |
216 std::string key; | 264 std::string key; |
217 if (!ImportPrivateKeyFileAsPkcs8(kTestEcdsaKeyFile, &key)) | 265 if (!ImportPrivateKeyFileAsPkcs8(kTestEcdsaKeyFile, &key)) |
218 return ScopedJava(); | 266 return ScopedJava(); |
219 return GetPKCS8PrivateKeyJava(PRIVATE_KEY_TYPE_ECDSA, key); | 267 return GetPKCS8PrivateKeyJava(PRIVATE_KEY_TYPE_ECDSA, key); |
220 } | 268 } |
221 | 269 |
222 // Call this function to verify that one message signed with our | 270 // Call this function to verify that one message signed with our |
223 // test ECDSA private key is correct. Since ECDSA signing introduces | 271 // test DSA private key is correct. Since DSA signing introduces |
224 // random elements in the signature, it is not possible to compare | 272 // random elements in the signature, it is not possible to compare |
225 // signature bits directly. However, one can use the public key | 273 // signature bits directly. However, one can use the public key |
226 // to do the check. | 274 // to do the check. |
227 bool VerifyTestECDSASignature(const base::StringPiece& message, | 275 bool VerifyTestECDSASignature(const base::StringPiece& message, |
228 const base::StringPiece& signature) { | 276 const base::StringPiece& signature) { |
229 crypto::ScopedEVP_PKEY pkey(ImportPublicKeyFile(kTestEcdsaPublicKeyFile)); | 277 crypto::ScopedEVP_PKEY pkey(ImportPublicKeyFile(kTestEcdsaPublicKeyFile)); |
230 if (!pkey.get()) | 278 if (!pkey.get()) |
231 return false; | 279 return false; |
232 crypto::ScopedEC_KEY pub_key(EVP_PKEY_get1_EC_KEY(pkey.get())); | 280 crypto::ScopedEC_KEY pub_key(EVP_PKEY_get1_EC_KEY(pkey.get())); |
233 if (!pub_key.get()) { | 281 if (!pub_key.get()) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 unsigned int p_len = 0; | 331 unsigned int p_len = 0; |
284 int ret = RSA_sign( | 332 int ret = RSA_sign( |
285 NID_md5_sha1, digest, digest_len, p, &p_len, rsa.get()); | 333 NID_md5_sha1, digest, digest_len, p, &p_len, rsa.get()); |
286 if (ret != 1) { | 334 if (ret != 1) { |
287 LOG(ERROR) << "RSA_sign() failed: " << GetOpenSSLErrorString(); | 335 LOG(ERROR) << "RSA_sign() failed: " << GetOpenSSLErrorString(); |
288 return false; | 336 return false; |
289 } | 337 } |
290 signature_size = static_cast<size_t>(p_len); | 338 signature_size = static_cast<size_t>(p_len); |
291 break; | 339 break; |
292 } | 340 } |
| 341 case EVP_PKEY_DSA: |
| 342 { |
| 343 crypto::ScopedDSA dsa(EVP_PKEY_get1_DSA(openssl_key)); |
| 344 if (!dsa.get()) { |
| 345 LOG(ERROR) << "Could not get DSA from EVP_PKEY: " |
| 346 << GetOpenSSLErrorString(); |
| 347 return false; |
| 348 } |
| 349 // Note, the actual signature can be smaller than DSA_size() |
| 350 max_signature_size = static_cast<size_t>(DSA_size(dsa.get())); |
| 351 unsigned char* p = OpenSSLWriteInto(&signature, |
| 352 max_signature_size); |
| 353 unsigned int p_len = 0; |
| 354 // Note: first parameter is ignored by function. |
| 355 int ret = DSA_sign(0, digest, digest_len, p, &p_len, dsa.get()); |
| 356 if (ret != 1) { |
| 357 LOG(ERROR) << "DSA_sign() failed: " << GetOpenSSLErrorString(); |
| 358 return false; |
| 359 } |
| 360 signature_size = static_cast<size_t>(p_len); |
| 361 break; |
| 362 } |
293 case EVP_PKEY_EC: | 363 case EVP_PKEY_EC: |
294 { | 364 { |
295 crypto::ScopedEC_KEY ecdsa(EVP_PKEY_get1_EC_KEY(openssl_key)); | 365 crypto::ScopedEC_KEY ecdsa(EVP_PKEY_get1_EC_KEY(openssl_key)); |
296 if (!ecdsa.get()) { | 366 if (!ecdsa.get()) { |
297 LOG(ERROR) << "Could not get EC_KEY from EVP_PKEY: " | 367 LOG(ERROR) << "Could not get EC_KEY from EVP_PKEY: " |
298 << GetOpenSSLErrorString(); | 368 << GetOpenSSLErrorString(); |
299 return false; | 369 return false; |
300 } | 370 } |
301 // Note, the actual signature can be smaller than ECDSA_size() | 371 // Note, the actual signature can be smaller than ECDSA_size() |
302 max_signature_size = ECDSA_size(ecdsa.get()); | 372 max_signature_size = ECDSA_size(ecdsa.get()); |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
442 NULL)); | 512 NULL)); |
443 ASSERT_TRUE(bn.get()); | 513 ASSERT_TRUE(bn.get()); |
444 | 514 |
445 // Compare it to the one in the RSA key, they must be identical. | 515 // Compare it to the one in the RSA key, they must be identical. |
446 crypto::ScopedRSA rsa(EVP_PKEY_get1_RSA(pkey.get())); | 516 crypto::ScopedRSA rsa(EVP_PKEY_get1_RSA(pkey.get())); |
447 ASSERT_TRUE(rsa.get()) << GetOpenSSLErrorString(); | 517 ASSERT_TRUE(rsa.get()) << GetOpenSSLErrorString(); |
448 | 518 |
449 ASSERT_EQ(0, BN_cmp(bn.get(), rsa.get()->n)); | 519 ASSERT_EQ(0, BN_cmp(bn.get(), rsa.get()->n)); |
450 } | 520 } |
451 | 521 |
| 522 TEST(AndroidKeyStore,GetDSAKeyParamQ) { |
| 523 crypto::OpenSSLErrStackTracer err_trace(FROM_HERE); |
| 524 InitEnv(); |
| 525 |
| 526 // Load the test DSA key. |
| 527 crypto::ScopedEVP_PKEY pkey(ImportPrivateKeyFile(kTestDsaKeyFile)); |
| 528 ASSERT_TRUE(pkey.get()); |
| 529 |
| 530 // Convert it to encoded PKCS#8 bytes. |
| 531 std::string pkcs8_data; |
| 532 ASSERT_TRUE(GetPrivateKeyPkcs8Bytes(pkey, &pkcs8_data)); |
| 533 |
| 534 // Create platform PrivateKey object from it. |
| 535 ScopedJava key_java = GetPKCS8PrivateKeyJava(PRIVATE_KEY_TYPE_DSA, |
| 536 pkcs8_data); |
| 537 ASSERT_FALSE(key_java.is_null()); |
| 538 |
| 539 // Retrieve the corresponding Q parameter through JNI |
| 540 std::vector<uint8> q_java; |
| 541 ASSERT_TRUE(GetDSAKeyParamQ(key_java.obj(), &q_java)); |
| 542 |
| 543 // Create an OpenSSL BIGNUM from it. |
| 544 crypto::ScopedBIGNUM bn( |
| 545 BN_bin2bn(reinterpret_cast<const unsigned char*>(&q_java[0]), |
| 546 static_cast<int>(q_java.size()), |
| 547 NULL)); |
| 548 ASSERT_TRUE(bn.get()); |
| 549 |
| 550 // Compare it to the one in the RSA key, they must be identical. |
| 551 crypto::ScopedDSA dsa(EVP_PKEY_get1_DSA(pkey.get())); |
| 552 ASSERT_TRUE(dsa.get()) << GetOpenSSLErrorString(); |
| 553 |
| 554 ASSERT_EQ(0, BN_cmp(bn.get(), dsa.get()->q)); |
| 555 } |
| 556 |
452 TEST(AndroidKeyStore,GetPrivateKeyTypeRSA) { | 557 TEST(AndroidKeyStore,GetPrivateKeyTypeRSA) { |
453 crypto::OpenSSLErrStackTracer err_trace(FROM_HERE); | 558 crypto::OpenSSLErrStackTracer err_trace(FROM_HERE); |
454 | 559 |
455 ScopedJava rsa_key = GetRSATestKeyJava(); | 560 ScopedJava rsa_key = GetRSATestKeyJava(); |
456 ASSERT_FALSE(rsa_key.is_null()); | 561 ASSERT_FALSE(rsa_key.is_null()); |
457 EXPECT_EQ(PRIVATE_KEY_TYPE_RSA, | 562 EXPECT_EQ(PRIVATE_KEY_TYPE_RSA, |
458 GetPrivateKeyType(rsa_key.obj())); | 563 GetPrivateKeyType(rsa_key.obj())); |
459 } | 564 } |
460 | 565 |
461 TEST(AndroidKeyStore,SignWithPrivateKeyRSA) { | 566 TEST(AndroidKeyStore,SignWithPrivateKeyRSA) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
504 | 609 |
505 std::string signature; | 610 std::string signature; |
506 DoKeySigningWithWrapper(wrapper_key.get(), | 611 DoKeySigningWithWrapper(wrapper_key.get(), |
507 openssl_key.get(), | 612 openssl_key.get(), |
508 message, | 613 message, |
509 &signature); | 614 &signature); |
510 ASSERT_TRUE( | 615 ASSERT_TRUE( |
511 CompareSignatureWithOpenSSL(message, signature, openssl_key.get())); | 616 CompareSignatureWithOpenSSL(message, signature, openssl_key.get())); |
512 } | 617 } |
513 | 618 |
| 619 TEST(AndroidKeyStore,GetPrivateKeyTypeDSA) { |
| 620 crypto::OpenSSLErrStackTracer err_trace(FROM_HERE); |
| 621 |
| 622 ScopedJava dsa_key = GetDSATestKeyJava(); |
| 623 ASSERT_FALSE(dsa_key.is_null()); |
| 624 EXPECT_EQ(PRIVATE_KEY_TYPE_DSA, |
| 625 GetPrivateKeyType(dsa_key.obj())); |
| 626 } |
| 627 |
| 628 TEST(AndroidKeyStore,SignWithPrivateKeyDSA) { |
| 629 ScopedJava dsa_key = GetDSATestKeyJava(); |
| 630 ASSERT_FALSE(dsa_key.is_null()); |
| 631 |
| 632 crypto::ScopedEVP_PKEY openssl_key(ImportPrivateKeyFile(kTestDsaKeyFile)); |
| 633 ASSERT_TRUE(openssl_key.get()); |
| 634 |
| 635 std::string message = kTestDsaHash; |
| 636 ASSERT_EQ(20U, message.size()); |
| 637 |
| 638 std::string signature; |
| 639 DoKeySigning(dsa_key.obj(), openssl_key.get(), message, &signature); |
| 640 ASSERT_TRUE(VerifyTestDSASignature(message, signature)); |
| 641 } |
| 642 |
| 643 TEST(AndroidKeyStore,SignWithWrapperKeyDSA) { |
| 644 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 645 |
| 646 ScopedJava dsa_key = GetDSATestKeyJava(); |
| 647 ASSERT_FALSE(dsa_key.is_null()); |
| 648 |
| 649 crypto::ScopedEVP_PKEY wrapper_key( |
| 650 GetOpenSSLPrivateKeyWrapper(dsa_key.obj())); |
| 651 ASSERT_TRUE(wrapper_key.get()); |
| 652 |
| 653 crypto::ScopedEVP_PKEY openssl_key(ImportPrivateKeyFile(kTestDsaKeyFile)); |
| 654 ASSERT_TRUE(openssl_key.get()); |
| 655 |
| 656 // Check that DSA_size() works correctly on the wrapper. |
| 657 EXPECT_EQ(EVP_PKEY_size(openssl_key.get()), |
| 658 EVP_PKEY_size(wrapper_key.get())); |
| 659 |
| 660 std::string message = kTestDsaHash; |
| 661 std::string signature; |
| 662 DoKeySigningWithWrapper(wrapper_key.get(), |
| 663 openssl_key.get(), |
| 664 message, |
| 665 &signature); |
| 666 ASSERT_TRUE(VerifyTestDSASignature(message, signature)); |
| 667 } |
| 668 |
514 TEST(AndroidKeyStore,GetPrivateKeyTypeECDSA) { | 669 TEST(AndroidKeyStore,GetPrivateKeyTypeECDSA) { |
515 crypto::OpenSSLErrStackTracer err_trace(FROM_HERE); | 670 crypto::OpenSSLErrStackTracer err_trace(FROM_HERE); |
516 | 671 |
517 ScopedJava ecdsa_key = GetECDSATestKeyJava(); | 672 ScopedJava ecdsa_key = GetECDSATestKeyJava(); |
518 ASSERT_FALSE(ecdsa_key.is_null()); | 673 ASSERT_FALSE(ecdsa_key.is_null()); |
519 EXPECT_EQ(PRIVATE_KEY_TYPE_ECDSA, | 674 EXPECT_EQ(PRIVATE_KEY_TYPE_ECDSA, |
520 GetPrivateKeyType(ecdsa_key.obj())); | 675 GetPrivateKeyType(ecdsa_key.obj())); |
521 } | 676 } |
522 | 677 |
523 TEST(AndroidKeyStore,SignWithPrivateKeyECDSA) { | 678 TEST(AndroidKeyStore,SignWithPrivateKeyECDSA) { |
(...skipping 30 matching lines...) Expand all Loading... |
554 std::string signature; | 709 std::string signature; |
555 DoKeySigningWithWrapper(wrapper_key.get(), | 710 DoKeySigningWithWrapper(wrapper_key.get(), |
556 openssl_key.get(), | 711 openssl_key.get(), |
557 message, | 712 message, |
558 &signature); | 713 &signature); |
559 ASSERT_TRUE(VerifyTestECDSASignature(message, signature)); | 714 ASSERT_TRUE(VerifyTestECDSASignature(message, signature)); |
560 } | 715 } |
561 | 716 |
562 } // namespace android | 717 } // namespace android |
563 } // namespace net | 718 } // namespace net |
OLD | NEW |