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 | |
256 const char kTestEcdsaKeyFile[] = "android-test-key-ecdsa.pem"; | 208 const char kTestEcdsaKeyFile[] = "android-test-key-ecdsa.pem"; |
257 const char kTestEcdsaPublicKeyFile[] = "android-test-key-ecdsa-public.pem"; | 209 const char kTestEcdsaPublicKeyFile[] = "android-test-key-ecdsa-public.pem"; |
258 | 210 |
259 // The test hash for ECDSA keys must be 20 bytes exactly. | 211 // The test hash for ECDSA keys must be 20 bytes exactly. |
260 const char kTestEcdsaHash[] = "0123456789ABCDEFGHIJ"; | 212 const char kTestEcdsaHash[] = "0123456789ABCDEFGHIJ"; |
261 | 213 |
262 // Retrieve a JNI local ref for our test ECDSA key. | 214 // Retrieve a JNI local ref for our test ECDSA key. |
263 ScopedJava GetECDSATestKeyJava() { | 215 ScopedJava GetECDSATestKeyJava() { |
264 std::string key; | 216 std::string key; |
265 if (!ImportPrivateKeyFileAsPkcs8(kTestEcdsaKeyFile, &key)) | 217 if (!ImportPrivateKeyFileAsPkcs8(kTestEcdsaKeyFile, &key)) |
266 return ScopedJava(); | 218 return ScopedJava(); |
267 return GetPKCS8PrivateKeyJava(PRIVATE_KEY_TYPE_ECDSA, key); | 219 return GetPKCS8PrivateKeyJava(PRIVATE_KEY_TYPE_ECDSA, key); |
268 } | 220 } |
269 | 221 |
270 // Call this function to verify that one message signed with our | 222 // Call this function to verify that one message signed with our |
271 // test DSA private key is correct. Since DSA signing introduces | 223 // test ECDSA private key is correct. Since ECDSA signing introduces |
272 // random elements in the signature, it is not possible to compare | 224 // random elements in the signature, it is not possible to compare |
273 // signature bits directly. However, one can use the public key | 225 // signature bits directly. However, one can use the public key |
274 // to do the check. | 226 // to do the check. |
275 bool VerifyTestECDSASignature(const base::StringPiece& message, | 227 bool VerifyTestECDSASignature(const base::StringPiece& message, |
276 const base::StringPiece& signature) { | 228 const base::StringPiece& signature) { |
277 crypto::ScopedEVP_PKEY pkey(ImportPublicKeyFile(kTestEcdsaPublicKeyFile)); | 229 crypto::ScopedEVP_PKEY pkey(ImportPublicKeyFile(kTestEcdsaPublicKeyFile)); |
278 if (!pkey.get()) | 230 if (!pkey.get()) |
279 return false; | 231 return false; |
280 crypto::ScopedEC_KEY pub_key(EVP_PKEY_get1_EC_KEY(pkey.get())); | 232 crypto::ScopedEC_KEY pub_key(EVP_PKEY_get1_EC_KEY(pkey.get())); |
281 if (!pub_key.get()) { | 233 if (!pub_key.get()) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
331 unsigned int p_len = 0; | 283 unsigned int p_len = 0; |
332 int ret = RSA_sign( | 284 int ret = RSA_sign( |
333 NID_md5_sha1, digest, digest_len, p, &p_len, rsa.get()); | 285 NID_md5_sha1, digest, digest_len, p, &p_len, rsa.get()); |
334 if (ret != 1) { | 286 if (ret != 1) { |
335 LOG(ERROR) << "RSA_sign() failed: " << GetOpenSSLErrorString(); | 287 LOG(ERROR) << "RSA_sign() failed: " << GetOpenSSLErrorString(); |
336 return false; | 288 return false; |
337 } | 289 } |
338 signature_size = static_cast<size_t>(p_len); | 290 signature_size = static_cast<size_t>(p_len); |
339 break; | 291 break; |
340 } | 292 } |
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 } | |
363 case EVP_PKEY_EC: | 293 case EVP_PKEY_EC: |
364 { | 294 { |
365 crypto::ScopedEC_KEY ecdsa(EVP_PKEY_get1_EC_KEY(openssl_key)); | 295 crypto::ScopedEC_KEY ecdsa(EVP_PKEY_get1_EC_KEY(openssl_key)); |
366 if (!ecdsa.get()) { | 296 if (!ecdsa.get()) { |
367 LOG(ERROR) << "Could not get EC_KEY from EVP_PKEY: " | 297 LOG(ERROR) << "Could not get EC_KEY from EVP_PKEY: " |
368 << GetOpenSSLErrorString(); | 298 << GetOpenSSLErrorString(); |
369 return false; | 299 return false; |
370 } | 300 } |
371 // Note, the actual signature can be smaller than ECDSA_size() | 301 // Note, the actual signature can be smaller than ECDSA_size() |
372 max_signature_size = ECDSA_size(ecdsa.get()); | 302 max_signature_size = ECDSA_size(ecdsa.get()); |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
512 NULL)); | 442 NULL)); |
513 ASSERT_TRUE(bn.get()); | 443 ASSERT_TRUE(bn.get()); |
514 | 444 |
515 // Compare it to the one in the RSA key, they must be identical. | 445 // Compare it to the one in the RSA key, they must be identical. |
516 crypto::ScopedRSA rsa(EVP_PKEY_get1_RSA(pkey.get())); | 446 crypto::ScopedRSA rsa(EVP_PKEY_get1_RSA(pkey.get())); |
517 ASSERT_TRUE(rsa.get()) << GetOpenSSLErrorString(); | 447 ASSERT_TRUE(rsa.get()) << GetOpenSSLErrorString(); |
518 | 448 |
519 ASSERT_EQ(0, BN_cmp(bn.get(), rsa.get()->n)); | 449 ASSERT_EQ(0, BN_cmp(bn.get(), rsa.get()->n)); |
520 } | 450 } |
521 | 451 |
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 | |
557 TEST(AndroidKeyStore,GetPrivateKeyTypeRSA) { | 452 TEST(AndroidKeyStore,GetPrivateKeyTypeRSA) { |
558 crypto::OpenSSLErrStackTracer err_trace(FROM_HERE); | 453 crypto::OpenSSLErrStackTracer err_trace(FROM_HERE); |
559 | 454 |
560 ScopedJava rsa_key = GetRSATestKeyJava(); | 455 ScopedJava rsa_key = GetRSATestKeyJava(); |
561 ASSERT_FALSE(rsa_key.is_null()); | 456 ASSERT_FALSE(rsa_key.is_null()); |
562 EXPECT_EQ(PRIVATE_KEY_TYPE_RSA, | 457 EXPECT_EQ(PRIVATE_KEY_TYPE_RSA, |
563 GetPrivateKeyType(rsa_key.obj())); | 458 GetPrivateKeyType(rsa_key.obj())); |
564 } | 459 } |
565 | 460 |
566 TEST(AndroidKeyStore,SignWithPrivateKeyRSA) { | 461 TEST(AndroidKeyStore,SignWithPrivateKeyRSA) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
609 | 504 |
610 std::string signature; | 505 std::string signature; |
611 DoKeySigningWithWrapper(wrapper_key.get(), | 506 DoKeySigningWithWrapper(wrapper_key.get(), |
612 openssl_key.get(), | 507 openssl_key.get(), |
613 message, | 508 message, |
614 &signature); | 509 &signature); |
615 ASSERT_TRUE( | 510 ASSERT_TRUE( |
616 CompareSignatureWithOpenSSL(message, signature, openssl_key.get())); | 511 CompareSignatureWithOpenSSL(message, signature, openssl_key.get())); |
617 } | 512 } |
618 | 513 |
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 | |
669 TEST(AndroidKeyStore,GetPrivateKeyTypeECDSA) { | 514 TEST(AndroidKeyStore,GetPrivateKeyTypeECDSA) { |
670 crypto::OpenSSLErrStackTracer err_trace(FROM_HERE); | 515 crypto::OpenSSLErrStackTracer err_trace(FROM_HERE); |
671 | 516 |
672 ScopedJava ecdsa_key = GetECDSATestKeyJava(); | 517 ScopedJava ecdsa_key = GetECDSATestKeyJava(); |
673 ASSERT_FALSE(ecdsa_key.is_null()); | 518 ASSERT_FALSE(ecdsa_key.is_null()); |
674 EXPECT_EQ(PRIVATE_KEY_TYPE_ECDSA, | 519 EXPECT_EQ(PRIVATE_KEY_TYPE_ECDSA, |
675 GetPrivateKeyType(ecdsa_key.obj())); | 520 GetPrivateKeyType(ecdsa_key.obj())); |
676 } | 521 } |
677 | 522 |
678 TEST(AndroidKeyStore,SignWithPrivateKeyECDSA) { | 523 TEST(AndroidKeyStore,SignWithPrivateKeyECDSA) { |
(...skipping 30 matching lines...) Expand all Loading... |
709 std::string signature; | 554 std::string signature; |
710 DoKeySigningWithWrapper(wrapper_key.get(), | 555 DoKeySigningWithWrapper(wrapper_key.get(), |
711 openssl_key.get(), | 556 openssl_key.get(), |
712 message, | 557 message, |
713 &signature); | 558 &signature); |
714 ASSERT_TRUE(VerifyTestECDSASignature(message, signature)); | 559 ASSERT_TRUE(VerifyTestECDSASignature(message, signature)); |
715 } | 560 } |
716 | 561 |
717 } // namespace android | 562 } // namespace android |
718 } // namespace net | 563 } // namespace net |
OLD | NEW |