Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(688)

Unified Diff: net/ssl/ssl_private_key_test_util.cc

Issue 2566273008: Use SecKeyCreateSignature on macOS 10.12 and later. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« net/ssl/ssl_private_key_test_util.h ('K') | « net/ssl/ssl_private_key_test_util.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/ssl/ssl_private_key_test_util.cc
diff --git a/net/ssl/ssl_private_key_test_util.cc b/net/ssl/ssl_private_key_test_util.cc
new file mode 100644
index 0000000000000000000000000000000000000000..4e43af3bc7b2cdce69c3700c5e1b4bb970e07807
--- /dev/null
+++ b/net/ssl/ssl_private_key_test_util.cc
@@ -0,0 +1,221 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/ssl/ssl_private_key_test_util.h"
+
+#include <stdint.h>
+
+#include <vector>
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/run_loop.h"
+#include "base/strings/string_util.h"
+#include "crypto/openssl_util.h"
+#include "net/base/net_errors.h"
+#include "net/ssl/ssl_private_key.h"
+#include "net/test/gtest_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/boringssl/src/include/openssl/bytestring.h"
+#include "third_party/boringssl/src/include/openssl/digest.h"
+#include "third_party/boringssl/src/include/openssl/ec.h"
+#include "third_party/boringssl/src/include/openssl/ec_key.h"
+#include "third_party/boringssl/src/include/openssl/evp.h"
+
+using net::test::IsOk;
+
+namespace net {
+
+namespace {
+
+const char* HashToString(SSLPrivateKey::Hash hash) {
+ switch (hash) {
+ case SSLPrivateKey::Hash::MD5_SHA1:
+ return "MD5_SHA1";
+ case SSLPrivateKey::Hash::SHA1:
+ return "SHA1";
+ case SSLPrivateKey::Hash::SHA256:
+ return "SHA256";
+ case SSLPrivateKey::Hash::SHA384:
+ return "SHA384";
+ case SSLPrivateKey::Hash::SHA512:
+ return "SHA512";
+ }
+
+ NOTREACHED();
+ return "";
+}
+
+const EVP_MD* HashToMD(SSLPrivateKey::Hash hash) {
+ switch (hash) {
+ case SSLPrivateKey::Hash::MD5_SHA1:
+ return EVP_md5_sha1();
+ case SSLPrivateKey::Hash::SHA1:
+ return EVP_sha1();
+ case SSLPrivateKey::Hash::SHA256:
+ return EVP_sha256();
+ case SSLPrivateKey::Hash::SHA384:
+ return EVP_sha384();
+ case SSLPrivateKey::Hash::SHA512:
+ return EVP_sha512();
+ }
+
+ NOTREACHED();
+ return nullptr;
+}
+
+SSLPrivateKey::Type TypeForOpenSSLKey(EVP_PKEY* pkey) {
+ switch (EVP_PKEY_id(pkey)) {
+ case EVP_PKEY_RSA:
+ return SSLPrivateKey::Type::RSA;
+ case EVP_PKEY_EC: {
+ switch (EC_GROUP_get_curve_name(
+ EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey)))) {
+ case NID_X9_62_prime256v1:
+ return SSLPrivateKey::Type::ECDSA_P256;
+ case NID_secp384r1:
+ return SSLPrivateKey::Type::ECDSA_P384;
+ case NID_secp521r1:
+ return SSLPrivateKey::Type::ECDSA_P521;
+ }
+ }
+ }
+
+ NOTREACHED();
+ return SSLPrivateKey::Type::RSA;
+}
+
+// Resize a string to |size| bytes of data, then return its data buffer address
+// cast as an 'uint8_t*', as expected by OpenSSL functions.
+// |str| the target string.
+// |size| the number of bytes to write into the string.
+// Return the string's new buffer in memory, as an 'uint8_t*' pointer.
+uint8_t* OpenSSLWriteInto(std::string* str, size_t size) {
+ return reinterpret_cast<uint8_t*>(base::WriteInto(str, size + 1));
+}
+
+bool VerifyWithOpenSSL(const EVP_MD* md,
+ const base::StringPiece& digest,
+ EVP_PKEY* key,
+ const base::StringPiece& signature) {
+ bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new(key, nullptr));
+ if (!ctx || !EVP_PKEY_verify_init(ctx.get()) ||
+ !EVP_PKEY_CTX_set_signature_md(ctx.get(), md) ||
+ !EVP_PKEY_verify(
+ ctx.get(), reinterpret_cast<const uint8_t*>(signature.data()),
+ signature.size(), reinterpret_cast<const uint8_t*>(digest.data()),
+ digest.size())) {
+ return false;
+ }
+
+ return true;
+}
+
+bool SignWithOpenSSL(const EVP_MD* md,
+ const base::StringPiece& digest,
+ EVP_PKEY* key,
+ std::string* result) {
+ size_t sig_len;
+ bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new(key, nullptr));
+ if (!ctx || !EVP_PKEY_sign_init(ctx.get()) ||
+ !EVP_PKEY_CTX_set_signature_md(ctx.get(), md) ||
+ !EVP_PKEY_sign(ctx.get(), OpenSSLWriteInto(result, EVP_PKEY_size(key)),
+ &sig_len, reinterpret_cast<const uint8_t*>(digest.data()),
+ digest.size())) {
+ return false;
+ }
+
+ result->resize(sig_len);
+ return true;
+}
+
+void OnSignComplete(base::RunLoop* loop,
+ Error* out_error,
+ std::string* out_signature,
+ Error error,
+ const std::vector<uint8_t>& signature) {
+ *out_error = error;
+ out_signature->assign(signature.begin(), signature.end());
+ loop->Quit();
+}
+
+Error DoKeySigningWithWrapper(SSLPrivateKey* key,
+ SSLPrivateKey::Hash hash,
+ const base::StringPiece& message,
+ std::string* result) {
+ Error error;
+ base::RunLoop loop;
+ key->SignDigest(
+ hash, message,
+ base::Bind(OnSignComplete, base::Unretained(&loop),
+ base::Unretained(&error), base::Unretained(result)));
+ loop.Run();
+ return error;
+}
+
+} // namespace
+
+const char* SSLPrivateKeyTypeToString(SSLPrivateKey::Type type) {
+ switch (type) {
+ case SSLPrivateKey::Type::RSA:
+ return "RSA";
+ case SSLPrivateKey::Type::ECDSA_P256:
+ return "ECDSA_P256";
+ case SSLPrivateKey::Type::ECDSA_P384:
+ return "ECDSA_P384";
+ case SSLPrivateKey::Type::ECDSA_P521:
+ return "ECDSA_P521";
+ }
+
+ NOTREACHED();
+ return "";
+}
+
+void TestSSLPrivateKeyMatches(SSLPrivateKey* key, const std::string& pkcs8) {
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+
+ // Create the equivalent OpenSSL key.
+ CBS cbs;
+ CBS_init(&cbs, reinterpret_cast<const uint8_t*>(pkcs8.data()), pkcs8.size());
+ bssl::UniquePtr<EVP_PKEY> openssl_key(EVP_parse_private_key(&cbs));
+ ASSERT_TRUE(openssl_key);
+ EXPECT_EQ(0u, CBS_len(&cbs));
+
+ // Check the length and type matches.
+ EXPECT_EQ(TypeForOpenSSLKey(openssl_key.get()), key->GetType());
+ EXPECT_EQ(static_cast<size_t>(EVP_PKEY_size(openssl_key.get())),
+ key->GetMaxSignatureLengthInBytes());
+
+ // Test all supported hash algorithms.
+ std::vector<SSLPrivateKey::Hash> hashes = key->GetDigestPreferences();
+
+ // To support TLS 1.1 and earlier, RSA keys must implicitly support MD5-SHA1,
+ // despite not being advertised.
+ if (key->GetType() == SSLPrivateKey::Type::RSA)
+ hashes.push_back(SSLPrivateKey::Hash::MD5_SHA1);
+
+ for (auto hash : hashes) {
Ryan Sleevi 2016/12/13 22:21:08 const auto&
davidben 2016/12/14 00:59:43 It's an enum. :-P Switched to a concrete type per
+ SCOPED_TRACE(HashToString(hash));
+ const EVP_MD* md = HashToMD(hash);
+
+ std::string digest(EVP_MD_size(md), 'a');
+
+ // Test the key generates valid signatures.
+ std::string signature;
+ Error error = DoKeySigningWithWrapper(key, hash, digest, &signature);
+ EXPECT_THAT(error, IsOk());
+ EXPECT_TRUE(VerifyWithOpenSSL(md, digest, openssl_key.get(), signature));
+
+ // RSA signing is deterministic, so further check the signature matches.
+ if (key->GetType() == SSLPrivateKey::Type::RSA) {
+ std::string openssl_signature;
+ ASSERT_TRUE(
+ SignWithOpenSSL(md, digest, openssl_key.get(), &openssl_signature));
+ EXPECT_EQ(openssl_signature, signature);
+ }
+ }
+}
+
+} // namespace net
« net/ssl/ssl_private_key_test_util.h ('K') | « net/ssl/ssl_private_key_test_util.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698