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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/ssl/ssl_private_key_test_util.h"
6
7 #include <stdint.h>
8
9 #include <vector>
10
11 #include "base/bind.h"
12 #include "base/location.h"
13 #include "base/logging.h"
14 #include "base/run_loop.h"
15 #include "base/strings/string_util.h"
16 #include "crypto/openssl_util.h"
17 #include "net/base/net_errors.h"
18 #include "net/ssl/ssl_private_key.h"
19 #include "net/test/gtest_util.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "third_party/boringssl/src/include/openssl/bytestring.h"
22 #include "third_party/boringssl/src/include/openssl/digest.h"
23 #include "third_party/boringssl/src/include/openssl/ec.h"
24 #include "third_party/boringssl/src/include/openssl/ec_key.h"
25 #include "third_party/boringssl/src/include/openssl/evp.h"
26
27 using net::test::IsOk;
28
29 namespace net {
30
31 namespace {
32
33 const char* HashToString(SSLPrivateKey::Hash hash) {
34 switch (hash) {
35 case SSLPrivateKey::Hash::MD5_SHA1:
36 return "MD5_SHA1";
37 case SSLPrivateKey::Hash::SHA1:
38 return "SHA1";
39 case SSLPrivateKey::Hash::SHA256:
40 return "SHA256";
41 case SSLPrivateKey::Hash::SHA384:
42 return "SHA384";
43 case SSLPrivateKey::Hash::SHA512:
44 return "SHA512";
45 }
46
47 NOTREACHED();
48 return "";
49 }
50
51 const EVP_MD* HashToMD(SSLPrivateKey::Hash hash) {
52 switch (hash) {
53 case SSLPrivateKey::Hash::MD5_SHA1:
54 return EVP_md5_sha1();
55 case SSLPrivateKey::Hash::SHA1:
56 return EVP_sha1();
57 case SSLPrivateKey::Hash::SHA256:
58 return EVP_sha256();
59 case SSLPrivateKey::Hash::SHA384:
60 return EVP_sha384();
61 case SSLPrivateKey::Hash::SHA512:
62 return EVP_sha512();
63 }
64
65 NOTREACHED();
66 return nullptr;
67 }
68
69 SSLPrivateKey::Type TypeForOpenSSLKey(EVP_PKEY* pkey) {
70 switch (EVP_PKEY_id(pkey)) {
71 case EVP_PKEY_RSA:
72 return SSLPrivateKey::Type::RSA;
73 case EVP_PKEY_EC: {
74 switch (EC_GROUP_get_curve_name(
75 EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey)))) {
76 case NID_X9_62_prime256v1:
77 return SSLPrivateKey::Type::ECDSA_P256;
78 case NID_secp384r1:
79 return SSLPrivateKey::Type::ECDSA_P384;
80 case NID_secp521r1:
81 return SSLPrivateKey::Type::ECDSA_P521;
82 }
83 }
84 }
85
86 NOTREACHED();
87 return SSLPrivateKey::Type::RSA;
88 }
89
90 // Resize a string to |size| bytes of data, then return its data buffer address
91 // cast as an 'uint8_t*', as expected by OpenSSL functions.
92 // |str| the target string.
93 // |size| the number of bytes to write into the string.
94 // Return the string's new buffer in memory, as an 'uint8_t*' pointer.
95 uint8_t* OpenSSLWriteInto(std::string* str, size_t size) {
96 return reinterpret_cast<uint8_t*>(base::WriteInto(str, size + 1));
97 }
98
99 bool VerifyWithOpenSSL(const EVP_MD* md,
100 const base::StringPiece& digest,
101 EVP_PKEY* key,
102 const base::StringPiece& signature) {
103 bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new(key, nullptr));
104 if (!ctx || !EVP_PKEY_verify_init(ctx.get()) ||
105 !EVP_PKEY_CTX_set_signature_md(ctx.get(), md) ||
106 !EVP_PKEY_verify(
107 ctx.get(), reinterpret_cast<const uint8_t*>(signature.data()),
108 signature.size(), reinterpret_cast<const uint8_t*>(digest.data()),
109 digest.size())) {
110 return false;
111 }
112
113 return true;
114 }
115
116 bool SignWithOpenSSL(const EVP_MD* md,
117 const base::StringPiece& digest,
118 EVP_PKEY* key,
119 std::string* result) {
120 size_t sig_len;
121 bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new(key, nullptr));
122 if (!ctx || !EVP_PKEY_sign_init(ctx.get()) ||
123 !EVP_PKEY_CTX_set_signature_md(ctx.get(), md) ||
124 !EVP_PKEY_sign(ctx.get(), OpenSSLWriteInto(result, EVP_PKEY_size(key)),
125 &sig_len, reinterpret_cast<const uint8_t*>(digest.data()),
126 digest.size())) {
127 return false;
128 }
129
130 result->resize(sig_len);
131 return true;
132 }
133
134 void OnSignComplete(base::RunLoop* loop,
135 Error* out_error,
136 std::string* out_signature,
137 Error error,
138 const std::vector<uint8_t>& signature) {
139 *out_error = error;
140 out_signature->assign(signature.begin(), signature.end());
141 loop->Quit();
142 }
143
144 Error DoKeySigningWithWrapper(SSLPrivateKey* key,
145 SSLPrivateKey::Hash hash,
146 const base::StringPiece& message,
147 std::string* result) {
148 Error error;
149 base::RunLoop loop;
150 key->SignDigest(
151 hash, message,
152 base::Bind(OnSignComplete, base::Unretained(&loop),
153 base::Unretained(&error), base::Unretained(result)));
154 loop.Run();
155 return error;
156 }
157
158 } // namespace
159
160 const char* SSLPrivateKeyTypeToString(SSLPrivateKey::Type type) {
161 switch (type) {
162 case SSLPrivateKey::Type::RSA:
163 return "RSA";
164 case SSLPrivateKey::Type::ECDSA_P256:
165 return "ECDSA_P256";
166 case SSLPrivateKey::Type::ECDSA_P384:
167 return "ECDSA_P384";
168 case SSLPrivateKey::Type::ECDSA_P521:
169 return "ECDSA_P521";
170 }
171
172 NOTREACHED();
173 return "";
174 }
175
176 void TestSSLPrivateKeyMatches(SSLPrivateKey* key, const std::string& pkcs8) {
177 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
178
179 // Create the equivalent OpenSSL key.
180 CBS cbs;
181 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(pkcs8.data()), pkcs8.size());
182 bssl::UniquePtr<EVP_PKEY> openssl_key(EVP_parse_private_key(&cbs));
183 ASSERT_TRUE(openssl_key);
184 EXPECT_EQ(0u, CBS_len(&cbs));
185
186 // Check the length and type matches.
187 EXPECT_EQ(TypeForOpenSSLKey(openssl_key.get()), key->GetType());
188 EXPECT_EQ(static_cast<size_t>(EVP_PKEY_size(openssl_key.get())),
189 key->GetMaxSignatureLengthInBytes());
190
191 // Test all supported hash algorithms.
192 std::vector<SSLPrivateKey::Hash> hashes = key->GetDigestPreferences();
193
194 // To support TLS 1.1 and earlier, RSA keys must implicitly support MD5-SHA1,
195 // despite not being advertised.
196 if (key->GetType() == SSLPrivateKey::Type::RSA)
197 hashes.push_back(SSLPrivateKey::Hash::MD5_SHA1);
198
199 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
200 SCOPED_TRACE(HashToString(hash));
201 const EVP_MD* md = HashToMD(hash);
202
203 std::string digest(EVP_MD_size(md), 'a');
204
205 // Test the key generates valid signatures.
206 std::string signature;
207 Error error = DoKeySigningWithWrapper(key, hash, digest, &signature);
208 EXPECT_THAT(error, IsOk());
209 EXPECT_TRUE(VerifyWithOpenSSL(md, digest, openssl_key.get(), signature));
210
211 // RSA signing is deterministic, so further check the signature matches.
212 if (key->GetType() == SSLPrivateKey::Type::RSA) {
213 std::string openssl_signature;
214 ASSERT_TRUE(
215 SignWithOpenSSL(md, digest, openssl_key.get(), &openssl_signature));
216 EXPECT_EQ(openssl_signature, signature);
217 }
218 }
219 }
220
221 } // namespace net
OLDNEW
« 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