| 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 "base/android/jni_android.h" | 5 #include "base/android/jni_android.h" |
| 6 #include "base/android/jni_array.h" | 6 #include "base/android/jni_array.h" |
| 7 #include "base/android/scoped_java_ref.h" | 7 #include "base/android/scoped_java_ref.h" |
| 8 #include "base/bind.h" | 8 #include "base/bind.h" |
| 9 #include "base/files/file_path.h" | 9 #include "base/files/file_path.h" |
| 10 #include "base/files/file_util.h" | 10 #include "base/files/file_util.h" |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 #include "third_party/boringssl/src/include/openssl/pem.h" | 28 #include "third_party/boringssl/src/include/openssl/pem.h" |
| 29 #include "third_party/boringssl/src/include/openssl/rsa.h" | 29 #include "third_party/boringssl/src/include/openssl/rsa.h" |
| 30 #include "third_party/boringssl/src/include/openssl/x509.h" | 30 #include "third_party/boringssl/src/include/openssl/x509.h" |
| 31 | 31 |
| 32 namespace net { | 32 namespace net { |
| 33 | 33 |
| 34 namespace { | 34 namespace { |
| 35 | 35 |
| 36 typedef base::android::ScopedJavaLocalRef<jobject> ScopedJava; | 36 typedef base::android::ScopedJavaLocalRef<jobject> ScopedJava; |
| 37 | 37 |
| 38 // Resize a string to |size| bytes of data, then return its data buffer | 38 // Resize a string to |size| bytes of data, then return its data buffer address |
| 39 // address cast as an 'unsigned char*', as expected by OpenSSL functions. | 39 // cast as an 'uint8_t*', as expected by OpenSSL functions. |
| 40 // |str| the target string. | 40 // |str| the target string. |
| 41 // |size| the number of bytes to write into the string. | 41 // |size| the number of bytes to write into the string. |
| 42 // Return the string's new buffer in memory, as an 'unsigned char*' | 42 // Return the string's new buffer in memory, as an 'uint8_t*' pointer. |
| 43 // pointer. | 43 uint8_t* OpenSSLWriteInto(std::string* str, size_t size) { |
| 44 unsigned char* OpenSSLWriteInto(std::string* str, size_t size) { | 44 return reinterpret_cast<uint8_t*>(base::WriteInto(str, size + 1)); |
| 45 return reinterpret_cast<unsigned char*>(base::WriteInto(str, size + 1)); | |
| 46 } | 45 } |
| 47 | 46 |
| 48 bool ReadTestFile(const char* filename, std::string* pkcs8) { | 47 bool ReadTestFile(const char* filename, std::string* pkcs8) { |
| 49 base::FilePath certs_dir = GetTestCertsDirectory(); | 48 base::FilePath certs_dir = GetTestCertsDirectory(); |
| 50 base::FilePath file_path = certs_dir.AppendASCII(filename); | 49 base::FilePath file_path = certs_dir.AppendASCII(filename); |
| 51 return base::ReadFileToString(file_path, pkcs8); | 50 return base::ReadFileToString(file_path, pkcs8); |
| 52 } | 51 } |
| 53 | 52 |
| 54 // Load a given private key file into an EVP_PKEY. | 53 // Parses a PKCS#8 key into an OpenSSL private key object. |
| 55 // |filename| is the key file path. | 54 bssl::UniquePtr<EVP_PKEY> ImportPrivateKeyOpenSSL(const std::string& pkcs8) { |
| 56 // Returns a new EVP_PKEY on success, NULL on failure. | |
| 57 bssl::UniquePtr<EVP_PKEY> ImportPrivateKeyFile(const char* filename) { | |
| 58 std::string pkcs8; | |
| 59 if (!ReadTestFile(filename, &pkcs8)) | |
| 60 return nullptr; | |
| 61 | |
| 62 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 55 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 63 CBS cbs; | 56 CBS cbs; |
| 64 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(pkcs8.data()), pkcs8.size()); | 57 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(pkcs8.data()), pkcs8.size()); |
| 65 bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_private_key(&cbs)); | 58 return bssl::UniquePtr<EVP_PKEY>(EVP_parse_private_key(&cbs)); |
| 66 if (!pkey) { | |
| 67 LOG(ERROR) << "Could not load private key file: " << filename; | |
| 68 return nullptr; | |
| 69 } | |
| 70 | |
| 71 return pkey; | |
| 72 } | |
| 73 | |
| 74 // Imports the public key from the specified test certificate. | |
| 75 bssl::UniquePtr<EVP_PKEY> ImportPublicKeyFromCertificateFile( | |
| 76 const char* filename) { | |
| 77 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | |
| 78 | |
| 79 scoped_refptr<X509Certificate> cert = | |
| 80 ImportCertFromFile(GetTestCertsDirectory(), filename); | |
| 81 if (!cert) { | |
| 82 LOG(ERROR) << "Could not open certificate file: " << filename; | |
| 83 return nullptr; | |
| 84 } | |
| 85 | |
| 86 bssl::UniquePtr<EVP_PKEY> pkey(X509_get_pubkey(cert->os_cert_handle())); | |
| 87 if (!pkey) { | |
| 88 LOG(ERROR) << "Could not load public key from certificate: " << filename; | |
| 89 return nullptr; | |
| 90 } | |
| 91 | |
| 92 return pkey; | |
| 93 } | 59 } |
| 94 | 60 |
| 95 // Retrieve a JNI local ref from encoded PKCS#8 data. | 61 // Retrieve a JNI local ref from encoded PKCS#8 data. |
| 96 ScopedJava GetPKCS8PrivateKeyJava(android::PrivateKeyType key_type, | 62 ScopedJava GetPKCS8PrivateKeyJava(android::PrivateKeyType key_type, |
| 97 const std::string& pkcs8_key) { | 63 const std::string& pkcs8_key) { |
| 98 JNIEnv* env = base::android::AttachCurrentThread(); | 64 JNIEnv* env = base::android::AttachCurrentThread(); |
| 99 base::android::ScopedJavaLocalRef<jbyteArray> bytes( | 65 base::android::ScopedJavaLocalRef<jbyteArray> bytes( |
| 100 base::android::ToJavaByteArray( | 66 base::android::ToJavaByteArray( |
| 101 env, reinterpret_cast<const uint8_t*>(pkcs8_key.data()), | 67 env, reinterpret_cast<const uint8_t*>(pkcs8_key.data()), |
| 102 pkcs8_key.size())); | 68 pkcs8_key.size())); |
| 103 | 69 |
| 104 ScopedJava key(Java_AndroidKeyStoreTestUtil_createPrivateKeyFromPKCS8( | 70 ScopedJava key(Java_AndroidKeyStoreTestUtil_createPrivateKeyFromPKCS8( |
| 105 env, key_type, bytes)); | 71 env, key_type, bytes)); |
| 106 | 72 |
| 107 return key; | 73 return key; |
| 108 } | 74 } |
| 109 | 75 |
| 110 const char kTestRsaKeyFile[] = "client_1.pk8"; | 76 bool VerifyWithOpenSSL(const EVP_MD* md, |
| 111 const char kTestRsaCertificateFile[] = "client_1.pem"; | 77 const base::StringPiece& digest, |
| 112 | 78 EVP_PKEY* key, |
| 113 // Retrieve a JNI local ref for our test RSA key. | 79 const base::StringPiece& signature) { |
| 114 ScopedJava GetRSATestKeyJava() { | |
| 115 std::string key; | |
| 116 if (!ReadTestFile(kTestRsaKeyFile, &key)) | |
| 117 return ScopedJava(); | |
| 118 return GetPKCS8PrivateKeyJava(android::PRIVATE_KEY_TYPE_RSA, key); | |
| 119 } | |
| 120 | |
| 121 const char kTestEcdsaKeyFile[] = "client_4.pk8"; | |
| 122 const char kTestEcdsaCertificateFile[] = "client_4.pem"; | |
| 123 | |
| 124 // Retrieve a JNI local ref for our test ECDSA key. | |
| 125 ScopedJava GetECDSATestKeyJava() { | |
| 126 std::string key; | |
| 127 if (!ReadTestFile(kTestEcdsaKeyFile, &key)) | |
| 128 return ScopedJava(); | |
| 129 return GetPKCS8PrivateKeyJava(android::PRIVATE_KEY_TYPE_ECDSA, key); | |
| 130 } | |
| 131 | |
| 132 // Call this function to verify that one message signed with our | |
| 133 // test ECDSA private key is correct. Since ECDSA signing introduces | |
| 134 // random elements in the signature, it is not possible to compare | |
| 135 // signature bits directly. However, one can use the public key | |
| 136 // to do the check. | |
| 137 bool VerifyTestECDSASignature(const base::StringPiece& message, | |
| 138 const base::StringPiece& signature) { | |
| 139 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 80 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 140 | 81 |
| 141 bssl::UniquePtr<EVP_PKEY> pkey = | 82 bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new(key, nullptr)); |
| 142 ImportPublicKeyFromCertificateFile(kTestEcdsaCertificateFile); | 83 if (!ctx || !EVP_PKEY_verify_init(ctx.get()) || |
| 143 if (!pkey) | 84 !EVP_PKEY_CTX_set_signature_md(ctx.get(), md) || |
| 144 return false; | 85 !EVP_PKEY_verify( |
| 145 | 86 ctx.get(), reinterpret_cast<const uint8_t*>(signature.data()), |
| 146 EC_KEY* pub_key = EVP_PKEY_get0_EC_KEY(pkey.get()); | 87 signature.size(), reinterpret_cast<const uint8_t*>(digest.data()), |
| 147 if (!pub_key) { | 88 digest.size())) { |
| 148 LOG(ERROR) << "Could not get ECDSA public key"; | |
| 149 return false; | 89 return false; |
| 150 } | 90 } |
| 151 | 91 |
| 152 const unsigned char* digest = | |
| 153 reinterpret_cast<const unsigned char*>(message.data()); | |
| 154 int digest_len = static_cast<int>(message.size()); | |
| 155 const unsigned char* sigbuf = | |
| 156 reinterpret_cast<const unsigned char*>(signature.data()); | |
| 157 int siglen = static_cast<int>(signature.size()); | |
| 158 | |
| 159 if (!ECDSA_verify(0, digest, digest_len, sigbuf, siglen, pub_key)) { | |
| 160 LOG(ERROR) << "ECDSA_verify() failed"; | |
| 161 return false; | |
| 162 } | |
| 163 return true; | 92 return true; |
| 164 } | 93 } |
| 165 | 94 |
| 166 // Sign a message with OpenSSL, return the result as a string. | 95 bool SignWithOpenSSL(const EVP_MD* md, |
| 167 // |message| is the message to be signed. | 96 const base::StringPiece& digest, |
| 168 // |openssl_key| is an OpenSSL EVP_PKEY to use. | 97 EVP_PKEY* key, |
| 169 // |result| receives the result. | |
| 170 // Returns true on success, false otherwise. | |
| 171 bool SignWithOpenSSL(int hash_nid, | |
| 172 const base::StringPiece& message, | |
| 173 EVP_PKEY* openssl_key, | |
| 174 std::string* result) { | 98 std::string* result) { |
| 175 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 99 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 176 | 100 |
| 177 RSA* rsa = EVP_PKEY_get0_RSA(openssl_key); | 101 size_t sig_len; |
| 178 if (!rsa) { | 102 bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new(key, nullptr)); |
| 179 LOG(ERROR) << "Could not get RSA from EVP_PKEY"; | 103 if (!ctx || !EVP_PKEY_sign_init(ctx.get()) || |
| 104 !EVP_PKEY_CTX_set_signature_md(ctx.get(), md) || |
| 105 !EVP_PKEY_sign(ctx.get(), OpenSSLWriteInto(result, EVP_PKEY_size(key)), |
| 106 &sig_len, reinterpret_cast<const uint8_t*>(digest.data()), |
| 107 digest.size())) { |
| 180 return false; | 108 return false; |
| 181 } | 109 } |
| 182 | 110 |
| 183 const unsigned char* digest = | 111 result->resize(sig_len); |
| 184 reinterpret_cast<const unsigned char*>(message.data()); | |
| 185 unsigned int digest_len = static_cast<unsigned int>(message.size()); | |
| 186 | |
| 187 // With RSA, the signature will always be RSA_size() bytes. | |
| 188 size_t max_signature_size = static_cast<size_t>(RSA_size(rsa)); | |
| 189 std::string signature; | |
| 190 unsigned char* p = OpenSSLWriteInto(&signature, max_signature_size); | |
| 191 unsigned int p_len = 0; | |
| 192 if (!RSA_sign(hash_nid, digest, digest_len, p, &p_len, rsa)) { | |
| 193 LOG(ERROR) << "RSA_sign() failed"; | |
| 194 return false; | |
| 195 } | |
| 196 | |
| 197 size_t signature_size = static_cast<size_t>(p_len); | |
| 198 if (signature_size == 0) { | |
| 199 LOG(ERROR) << "Signature is empty!"; | |
| 200 return false; | |
| 201 } | |
| 202 if (signature_size > max_signature_size) { | |
| 203 LOG(ERROR) << "Signature size mismatch, actual " << signature_size | |
| 204 << ", expected <= " << max_signature_size; | |
| 205 return false; | |
| 206 } | |
| 207 signature.resize(signature_size); | |
| 208 result->swap(signature); | |
| 209 return true; | 112 return true; |
| 210 } | 113 } |
| 211 | 114 |
| 212 // Check that a generated signature for a given message matches | |
| 213 // OpenSSL output byte-by-byte. | |
| 214 // |message| is the input message. | |
| 215 // |signature| is the generated signature for the message. | |
| 216 // |openssl_key| is a raw EVP_PKEY for the same private key than the | |
| 217 // one which was used to generate the signature. | |
| 218 // Returns true on success, false otherwise. | |
| 219 bool CompareSignatureWithOpenSSL(int hash_nid, | |
| 220 const base::StringPiece& message, | |
| 221 const base::StringPiece& signature, | |
| 222 EVP_PKEY* openssl_key) { | |
| 223 std::string openssl_signature; | |
| 224 if (!SignWithOpenSSL(hash_nid, message, openssl_key, &openssl_signature)) | |
| 225 return false; | |
| 226 | |
| 227 if (signature.size() != openssl_signature.size()) { | |
| 228 LOG(ERROR) << "Signature size mismatch, actual " << signature.size() | |
| 229 << ", expected " << openssl_signature.size(); | |
| 230 return false; | |
| 231 } | |
| 232 for (size_t n = 0; n < signature.size(); ++n) { | |
| 233 if (openssl_signature[n] != signature[n]) { | |
| 234 LOG(ERROR) << "Signature byte mismatch at index " << n << "actual " | |
| 235 << signature[n] << ", expected " << openssl_signature[n]; | |
| 236 LOG(ERROR) << "Actual signature : " | |
| 237 << base::HexEncode(signature.data(), signature.size()); | |
| 238 LOG(ERROR) << "Expected signature: " | |
| 239 << base::HexEncode(openssl_signature.data(), | |
| 240 openssl_signature.size()); | |
| 241 return false; | |
| 242 } | |
| 243 } | |
| 244 return true; | |
| 245 } | |
| 246 | |
| 247 void OnSignComplete(base::RunLoop* loop, | 115 void OnSignComplete(base::RunLoop* loop, |
| 248 Error* out_error, | 116 Error* out_error, |
| 249 std::string* out_signature, | 117 std::string* out_signature, |
| 250 Error error, | 118 Error error, |
| 251 const std::vector<uint8_t>& signature) { | 119 const std::vector<uint8_t>& signature) { |
| 252 *out_error = error; | 120 *out_error = error; |
| 253 out_signature->assign(signature.begin(), signature.end()); | 121 out_signature->assign(signature.begin(), signature.end()); |
| 254 loop->Quit(); | 122 loop->Quit(); |
| 255 } | 123 } |
| 256 | 124 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 275 int nid; | 143 int nid; |
| 276 SSLPrivateKey::Hash hash; | 144 SSLPrivateKey::Hash hash; |
| 277 } kHashes[] = { | 145 } kHashes[] = { |
| 278 {"MD5-SHA1", NID_md5_sha1, SSLPrivateKey::Hash::MD5_SHA1}, | 146 {"MD5-SHA1", NID_md5_sha1, SSLPrivateKey::Hash::MD5_SHA1}, |
| 279 {"SHA-1", NID_sha1, SSLPrivateKey::Hash::SHA1}, | 147 {"SHA-1", NID_sha1, SSLPrivateKey::Hash::SHA1}, |
| 280 {"SHA-256", NID_sha256, SSLPrivateKey::Hash::SHA256}, | 148 {"SHA-256", NID_sha256, SSLPrivateKey::Hash::SHA256}, |
| 281 {"SHA-384", NID_sha384, SSLPrivateKey::Hash::SHA384}, | 149 {"SHA-384", NID_sha384, SSLPrivateKey::Hash::SHA384}, |
| 282 {"SHA-512", NID_sha512, SSLPrivateKey::Hash::SHA512}, | 150 {"SHA-512", NID_sha512, SSLPrivateKey::Hash::SHA512}, |
| 283 }; | 151 }; |
| 284 | 152 |
| 153 struct TestKey { |
| 154 const char* cert_file; |
| 155 const char* key_file; |
| 156 android::PrivateKeyType android_key_type; |
| 157 SSLPrivateKey::Type key_type; |
| 158 }; |
| 159 |
| 160 static const TestKey kTestKeys[] = { |
| 161 {"client_1.pem", "client_1.pk8", android::PRIVATE_KEY_TYPE_RSA, |
| 162 SSLPrivateKey::Type::RSA}, |
| 163 {"client_4.pem", "client_4.pk8", android::PRIVATE_KEY_TYPE_ECDSA, |
| 164 SSLPrivateKey::Type::ECDSA_P256}, |
| 165 {"client_5.pem", "client_5.pk8", android::PRIVATE_KEY_TYPE_ECDSA, |
| 166 SSLPrivateKey::Type::ECDSA_P384}, |
| 167 {"client_6.pem", "client_6.pk8", android::PRIVATE_KEY_TYPE_ECDSA, |
| 168 SSLPrivateKey::Type::ECDSA_P521}, |
| 169 }; |
| 170 |
| 285 } // namespace | 171 } // namespace |
| 286 | 172 |
| 287 TEST(SSLPlatformKeyAndroid, RSA) { | 173 class SSLPlatformKeyAndroidTest : public testing::TestWithParam<TestKey> {}; |
| 174 |
| 175 TEST_P(SSLPlatformKeyAndroidTest, SignHashes) { |
| 288 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 176 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 177 const TestKey& test_key = GetParam(); |
| 289 | 178 |
| 290 scoped_refptr<X509Certificate> cert = | 179 scoped_refptr<X509Certificate> cert = |
| 291 ImportCertFromFile(GetTestCertsDirectory(), kTestRsaCertificateFile); | 180 ImportCertFromFile(GetTestCertsDirectory(), test_key.cert_file); |
| 292 ASSERT_TRUE(cert); | 181 ASSERT_TRUE(cert); |
| 293 ScopedJava rsa_key = GetRSATestKeyJava(); | 182 |
| 294 ASSERT_FALSE(rsa_key.is_null()); | 183 std::string key_bytes; |
| 184 ASSERT_TRUE(ReadTestFile(test_key.key_file, &key_bytes)); |
| 185 ScopedJava java_key = |
| 186 GetPKCS8PrivateKeyJava(test_key.android_key_type, key_bytes); |
| 187 ASSERT_FALSE(java_key.is_null()); |
| 295 | 188 |
| 296 scoped_refptr<SSLPrivateKey> wrapper_key = | 189 scoped_refptr<SSLPrivateKey> wrapper_key = |
| 297 WrapJavaPrivateKey(cert.get(), rsa_key); | 190 WrapJavaPrivateKey(cert.get(), java_key); |
| 298 ASSERT_TRUE(wrapper_key); | 191 ASSERT_TRUE(wrapper_key); |
| 299 | 192 |
| 300 bssl::UniquePtr<EVP_PKEY> openssl_key = ImportPrivateKeyFile(kTestRsaKeyFile); | 193 bssl::UniquePtr<EVP_PKEY> openssl_key = ImportPrivateKeyOpenSSL(key_bytes); |
| 301 ASSERT_TRUE(openssl_key); | 194 ASSERT_TRUE(openssl_key); |
| 302 | 195 |
| 303 // Check that the wrapper key returns the correct length and type. | 196 // Check that the wrapper key returns the correct length and type. |
| 304 EXPECT_EQ(SSLPrivateKey::Type::RSA, wrapper_key->GetType()); | 197 EXPECT_EQ(test_key.key_type, wrapper_key->GetType()); |
| 305 EXPECT_EQ(static_cast<size_t>(EVP_PKEY_size(openssl_key.get())), | 198 EXPECT_EQ(static_cast<size_t>(EVP_PKEY_size(openssl_key.get())), |
| 306 wrapper_key->GetMaxSignatureLengthInBytes()); | 199 wrapper_key->GetMaxSignatureLengthInBytes()); |
| 307 | 200 |
| 308 // Test signing against each hash. | 201 // Test signing against each hash. |
| 309 for (const auto& hash : kHashes) { | 202 for (const auto& hash : kHashes) { |
| 203 // Only RSA signs MD5-SHA1. |
| 204 if (test_key.key_type != SSLPrivateKey::Type::RSA && |
| 205 hash.nid == NID_md5_sha1) { |
| 206 continue; |
| 207 } |
| 208 |
| 310 SCOPED_TRACE(hash.name); | 209 SCOPED_TRACE(hash.name); |
| 311 | 210 |
| 312 const EVP_MD* md = EVP_get_digestbynid(hash.nid); | 211 const EVP_MD* md = EVP_get_digestbynid(hash.nid); |
| 313 ASSERT_TRUE(md); | 212 ASSERT_TRUE(md); |
| 314 std::string digest(EVP_MD_size(md), 'a'); | 213 std::string digest(EVP_MD_size(md), 'a'); |
| 315 | 214 |
| 316 std::string signature; | 215 std::string signature; |
| 317 DoKeySigningWithWrapper(wrapper_key.get(), hash.hash, digest, &signature); | 216 DoKeySigningWithWrapper(wrapper_key.get(), hash.hash, digest, &signature); |
| 318 ASSERT_TRUE(CompareSignatureWithOpenSSL(hash.nid, digest, signature, | 217 EXPECT_TRUE(VerifyWithOpenSSL(md, digest, openssl_key.get(), signature)); |
| 319 openssl_key.get())); | 218 |
| 219 // RSA signing is deterministic, so further check the signature matches. |
| 220 if (test_key.key_type == SSLPrivateKey::Type::RSA) { |
| 221 std::string openssl_signature; |
| 222 ASSERT_TRUE( |
| 223 SignWithOpenSSL(md, digest, openssl_key.get(), &openssl_signature)); |
| 224 EXPECT_EQ(openssl_signature, signature); |
| 225 } |
| 320 } | 226 } |
| 321 } | 227 } |
| 322 | 228 |
| 323 TEST(SSLPlatformKeyAndroid, ECDSA) { | 229 INSTANTIATE_TEST_CASE_P(, |
| 324 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 230 SSLPlatformKeyAndroidTest, |
| 325 | 231 testing::ValuesIn(kTestKeys)); |
| 326 scoped_refptr<X509Certificate> cert = | |
| 327 ImportCertFromFile(GetTestCertsDirectory(), kTestEcdsaCertificateFile); | |
| 328 ASSERT_TRUE(cert); | |
| 329 ScopedJava ecdsa_key = GetECDSATestKeyJava(); | |
| 330 ASSERT_FALSE(ecdsa_key.is_null()); | |
| 331 | |
| 332 scoped_refptr<SSLPrivateKey> wrapper_key = | |
| 333 WrapJavaPrivateKey(cert.get(), ecdsa_key); | |
| 334 ASSERT_TRUE(wrapper_key); | |
| 335 | |
| 336 bssl::UniquePtr<EVP_PKEY> openssl_key = | |
| 337 ImportPrivateKeyFile(kTestEcdsaKeyFile); | |
| 338 ASSERT_TRUE(openssl_key); | |
| 339 | |
| 340 // Check that the wrapper key returns the correct length and type. | |
| 341 EXPECT_EQ(SSLPrivateKey::Type::ECDSA_P256, wrapper_key->GetType()); | |
| 342 EXPECT_EQ(static_cast<size_t>(EVP_PKEY_size(openssl_key.get())), | |
| 343 wrapper_key->GetMaxSignatureLengthInBytes()); | |
| 344 | |
| 345 // Test signing against each hash. | |
| 346 for (const auto& hash : kHashes) { | |
| 347 // ECDSA does not sign MD5-SHA1. | |
| 348 if (hash.nid == NID_md5_sha1) | |
| 349 continue; | |
| 350 | |
| 351 SCOPED_TRACE(hash.name); | |
| 352 const EVP_MD* md = EVP_get_digestbynid(hash.nid); | |
| 353 ASSERT_TRUE(md); | |
| 354 std::string digest(EVP_MD_size(md), 'a'); | |
| 355 | |
| 356 std::string signature; | |
| 357 DoKeySigningWithWrapper(wrapper_key.get(), hash.hash, digest, &signature); | |
| 358 ASSERT_TRUE(VerifyTestECDSASignature(digest, signature)); | |
| 359 } | |
| 360 } | |
| 361 | 232 |
| 362 } // namespace net | 233 } // namespace net |
| OLD | NEW |