| Index: trunk/src/net/android/keystore_unittest.cc
|
| ===================================================================
|
| --- trunk/src/net/android/keystore_unittest.cc (revision 283844)
|
| +++ trunk/src/net/android/keystore_unittest.cc (working copy)
|
| @@ -205,6 +205,54 @@
|
| return GetPKCS8PrivateKeyJava(PRIVATE_KEY_TYPE_RSA, key);
|
| }
|
|
|
| +const char kTestDsaKeyFile[] = "android-test-key-dsa.pem";
|
| +const char kTestDsaPublicKeyFile[] = "android-test-key-dsa-public.pem";
|
| +
|
| +// The DSA test hash must be 20 bytes exactly.
|
| +const char kTestDsaHash[] = "0123456789ABCDEFGHIJ";
|
| +
|
| +// Retrieve a JNI local ref for our test DSA key.
|
| +ScopedJava GetDSATestKeyJava() {
|
| + std::string key;
|
| + if (!ImportPrivateKeyFileAsPkcs8(kTestDsaKeyFile, &key))
|
| + return ScopedJava();
|
| + return GetPKCS8PrivateKeyJava(PRIVATE_KEY_TYPE_DSA, key);
|
| +}
|
| +
|
| +// Call this function to verify that one message signed with our
|
| +// test DSA private key is correct. Since DSA signing introduces
|
| +// random elements in the signature, it is not possible to compare
|
| +// signature bits directly. However, one can use the public key
|
| +// to do the check.
|
| +bool VerifyTestDSASignature(const base::StringPiece& message,
|
| + const base::StringPiece& signature) {
|
| + crypto::ScopedEVP_PKEY pkey(ImportPublicKeyFile(kTestDsaPublicKeyFile));
|
| + if (!pkey.get())
|
| + return false;
|
| +
|
| + crypto::ScopedDSA pub_key(EVP_PKEY_get1_DSA(pkey.get()));
|
| + if (!pub_key.get()) {
|
| + LOG(ERROR) << "Could not get DSA public key: "
|
| + << GetOpenSSLErrorString();
|
| + return false;
|
| + }
|
| +
|
| + const unsigned char* digest =
|
| + reinterpret_cast<const unsigned char*>(message.data());
|
| + int digest_len = static_cast<int>(message.size());
|
| + const unsigned char* sigbuf =
|
| + reinterpret_cast<const unsigned char*>(signature.data());
|
| + int siglen = static_cast<int>(signature.size());
|
| +
|
| + int ret = DSA_verify(
|
| + 0, digest, digest_len, sigbuf, siglen, pub_key.get());
|
| + if (ret != 1) {
|
| + LOG(ERROR) << "DSA_verify() failed: " << GetOpenSSLErrorString();
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| const char kTestEcdsaKeyFile[] = "android-test-key-ecdsa.pem";
|
| const char kTestEcdsaPublicKeyFile[] = "android-test-key-ecdsa-public.pem";
|
|
|
| @@ -220,7 +268,7 @@
|
| }
|
|
|
| // Call this function to verify that one message signed with our
|
| -// test ECDSA private key is correct. Since ECDSA signing introduces
|
| +// test DSA private key is correct. Since DSA signing introduces
|
| // random elements in the signature, it is not possible to compare
|
| // signature bits directly. However, one can use the public key
|
| // to do the check.
|
| @@ -290,6 +338,28 @@
|
| signature_size = static_cast<size_t>(p_len);
|
| break;
|
| }
|
| + case EVP_PKEY_DSA:
|
| + {
|
| + crypto::ScopedDSA dsa(EVP_PKEY_get1_DSA(openssl_key));
|
| + if (!dsa.get()) {
|
| + LOG(ERROR) << "Could not get DSA from EVP_PKEY: "
|
| + << GetOpenSSLErrorString();
|
| + return false;
|
| + }
|
| + // Note, the actual signature can be smaller than DSA_size()
|
| + max_signature_size = static_cast<size_t>(DSA_size(dsa.get()));
|
| + unsigned char* p = OpenSSLWriteInto(&signature,
|
| + max_signature_size);
|
| + unsigned int p_len = 0;
|
| + // Note: first parameter is ignored by function.
|
| + int ret = DSA_sign(0, digest, digest_len, p, &p_len, dsa.get());
|
| + if (ret != 1) {
|
| + LOG(ERROR) << "DSA_sign() failed: " << GetOpenSSLErrorString();
|
| + return false;
|
| + }
|
| + signature_size = static_cast<size_t>(p_len);
|
| + break;
|
| + }
|
| case EVP_PKEY_EC:
|
| {
|
| crypto::ScopedEC_KEY ecdsa(EVP_PKEY_get1_EC_KEY(openssl_key));
|
| @@ -449,6 +519,41 @@
|
| ASSERT_EQ(0, BN_cmp(bn.get(), rsa.get()->n));
|
| }
|
|
|
| +TEST(AndroidKeyStore,GetDSAKeyParamQ) {
|
| + crypto::OpenSSLErrStackTracer err_trace(FROM_HERE);
|
| + InitEnv();
|
| +
|
| + // Load the test DSA key.
|
| + crypto::ScopedEVP_PKEY pkey(ImportPrivateKeyFile(kTestDsaKeyFile));
|
| + ASSERT_TRUE(pkey.get());
|
| +
|
| + // Convert it to encoded PKCS#8 bytes.
|
| + std::string pkcs8_data;
|
| + ASSERT_TRUE(GetPrivateKeyPkcs8Bytes(pkey, &pkcs8_data));
|
| +
|
| + // Create platform PrivateKey object from it.
|
| + ScopedJava key_java = GetPKCS8PrivateKeyJava(PRIVATE_KEY_TYPE_DSA,
|
| + pkcs8_data);
|
| + ASSERT_FALSE(key_java.is_null());
|
| +
|
| + // Retrieve the corresponding Q parameter through JNI
|
| + std::vector<uint8> q_java;
|
| + ASSERT_TRUE(GetDSAKeyParamQ(key_java.obj(), &q_java));
|
| +
|
| + // Create an OpenSSL BIGNUM from it.
|
| + crypto::ScopedBIGNUM bn(
|
| + BN_bin2bn(reinterpret_cast<const unsigned char*>(&q_java[0]),
|
| + static_cast<int>(q_java.size()),
|
| + NULL));
|
| + ASSERT_TRUE(bn.get());
|
| +
|
| + // Compare it to the one in the RSA key, they must be identical.
|
| + crypto::ScopedDSA dsa(EVP_PKEY_get1_DSA(pkey.get()));
|
| + ASSERT_TRUE(dsa.get()) << GetOpenSSLErrorString();
|
| +
|
| + ASSERT_EQ(0, BN_cmp(bn.get(), dsa.get()->q));
|
| +}
|
| +
|
| TEST(AndroidKeyStore,GetPrivateKeyTypeRSA) {
|
| crypto::OpenSSLErrStackTracer err_trace(FROM_HERE);
|
|
|
| @@ -511,6 +616,56 @@
|
| CompareSignatureWithOpenSSL(message, signature, openssl_key.get()));
|
| }
|
|
|
| +TEST(AndroidKeyStore,GetPrivateKeyTypeDSA) {
|
| + crypto::OpenSSLErrStackTracer err_trace(FROM_HERE);
|
| +
|
| + ScopedJava dsa_key = GetDSATestKeyJava();
|
| + ASSERT_FALSE(dsa_key.is_null());
|
| + EXPECT_EQ(PRIVATE_KEY_TYPE_DSA,
|
| + GetPrivateKeyType(dsa_key.obj()));
|
| +}
|
| +
|
| +TEST(AndroidKeyStore,SignWithPrivateKeyDSA) {
|
| + ScopedJava dsa_key = GetDSATestKeyJava();
|
| + ASSERT_FALSE(dsa_key.is_null());
|
| +
|
| + crypto::ScopedEVP_PKEY openssl_key(ImportPrivateKeyFile(kTestDsaKeyFile));
|
| + ASSERT_TRUE(openssl_key.get());
|
| +
|
| + std::string message = kTestDsaHash;
|
| + ASSERT_EQ(20U, message.size());
|
| +
|
| + std::string signature;
|
| + DoKeySigning(dsa_key.obj(), openssl_key.get(), message, &signature);
|
| + ASSERT_TRUE(VerifyTestDSASignature(message, signature));
|
| +}
|
| +
|
| +TEST(AndroidKeyStore,SignWithWrapperKeyDSA) {
|
| + crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
|
| +
|
| + ScopedJava dsa_key = GetDSATestKeyJava();
|
| + ASSERT_FALSE(dsa_key.is_null());
|
| +
|
| + crypto::ScopedEVP_PKEY wrapper_key(
|
| + GetOpenSSLPrivateKeyWrapper(dsa_key.obj()));
|
| + ASSERT_TRUE(wrapper_key.get());
|
| +
|
| + crypto::ScopedEVP_PKEY openssl_key(ImportPrivateKeyFile(kTestDsaKeyFile));
|
| + ASSERT_TRUE(openssl_key.get());
|
| +
|
| + // Check that DSA_size() works correctly on the wrapper.
|
| + EXPECT_EQ(EVP_PKEY_size(openssl_key.get()),
|
| + EVP_PKEY_size(wrapper_key.get()));
|
| +
|
| + std::string message = kTestDsaHash;
|
| + std::string signature;
|
| + DoKeySigningWithWrapper(wrapper_key.get(),
|
| + openssl_key.get(),
|
| + message,
|
| + &signature);
|
| + ASSERT_TRUE(VerifyTestDSASignature(message, signature));
|
| +}
|
| +
|
| TEST(AndroidKeyStore,GetPrivateKeyTypeECDSA) {
|
| crypto::OpenSSLErrStackTracer err_trace(FROM_HERE);
|
|
|
|
|