OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 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 "base/logging.h" | |
6 #include "base/stl_util.h" | |
7 #include "content/child/webcrypto/algorithm_dispatch.h" | |
8 #include "content/child/webcrypto/crypto_data.h" | |
9 #include "content/child/webcrypto/jwk.h" | |
10 #include "content/child/webcrypto/status.h" | |
11 #include "content/child/webcrypto/test/test_helpers.h" | |
12 #include "content/child/webcrypto/webcrypto_util.h" | |
13 #include "testing/gtest/include/gtest/gtest.h" | |
14 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" | |
15 #include "third_party/WebKit/public/platform/WebCryptoKey.h" | |
16 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" | |
17 | |
18 namespace content { | |
19 | |
20 namespace webcrypto { | |
21 | |
22 namespace { | |
23 | |
24 bool SupportsRsaPss() { | |
25 #if defined(USE_OPENSSL) | |
26 return true; | |
27 #else | |
28 return false; | |
29 #endif | |
30 } | |
31 | |
32 blink::WebCryptoAlgorithm CreateRsaPssAlgorithm( | |
33 unsigned int salt_length_bytes) { | |
34 return blink::WebCryptoAlgorithm::adoptParamsAndCreate( | |
35 blink::WebCryptoAlgorithmIdRsaPss, | |
36 new blink::WebCryptoRsaPssParams(salt_length_bytes)); | |
37 } | |
38 | |
39 // Test that no two RSA-PSS signatures are identical, when using a non-zero | |
40 // lengthed salt. | |
41 TEST(WebCryptoRsaPssTest, SignIsRandom) { | |
42 if (!SupportsRsaPss()) { | |
43 LOG(WARNING) << "Skipping test because RSA-PSS is not supported"; | |
44 return; | |
45 } | |
46 | |
47 // Import public/private key pair. | |
48 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); | |
49 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); | |
50 | |
51 ImportRsaKeyPair( | |
52 HexStringToBytes(kPublicKeySpkiDerHex), | |
53 HexStringToBytes(kPrivateKeyPkcs8DerHex), | |
54 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaPss, | |
55 blink::WebCryptoAlgorithmIdSha1), | |
56 true, | |
57 blink::WebCryptoKeyUsageVerify, | |
58 blink::WebCryptoKeyUsageSign, | |
59 &public_key, | |
60 &private_key); | |
61 | |
62 // Use a 20-byte length salt. | |
63 blink::WebCryptoAlgorithm params = CreateRsaPssAlgorithm(20); | |
64 | |
65 // Some random message to sign. | |
66 std::vector<uint8_t> message = HexStringToBytes(kPublicKeySpkiDerHex); | |
67 | |
68 // Sign twice. | |
69 std::vector<uint8_t> signature1; | |
70 std::vector<uint8_t> signature2; | |
71 | |
72 ASSERT_EQ(Status::Success(), | |
73 Sign(params, private_key, CryptoData(message), &signature1)); | |
74 ASSERT_EQ(Status::Success(), | |
75 Sign(params, private_key, CryptoData(message), &signature2)); | |
76 | |
77 // The signatures will be different because of the salt. | |
78 EXPECT_NE(CryptoData(signature1), CryptoData(signature2)); | |
79 | |
80 // However both signatures should work when verifying. | |
81 bool is_match = false; | |
82 | |
83 ASSERT_EQ(Status::Success(), | |
84 Verify(params, | |
85 public_key, | |
86 CryptoData(signature1), | |
87 CryptoData(message), | |
88 &is_match)); | |
89 EXPECT_TRUE(is_match); | |
90 | |
91 ASSERT_EQ(Status::Success(), | |
92 Verify(params, | |
93 public_key, | |
94 CryptoData(signature2), | |
95 CryptoData(message), | |
96 &is_match)); | |
97 EXPECT_TRUE(is_match); | |
98 | |
99 // Corrupt the signature and verification must fail. | |
100 ASSERT_EQ(Status::Success(), | |
101 Verify(params, | |
102 public_key, | |
103 CryptoData(Corrupted(signature2)), | |
104 CryptoData(message), | |
105 &is_match)); | |
106 EXPECT_FALSE(is_match); | |
107 } | |
108 | |
109 // Try signing and verifying when the salt length is 0. The signature in this | |
110 // case is not random. | |
111 TEST(WebCryptoRsaPssTest, SignVerifyNoSalt) { | |
112 if (!SupportsRsaPss()) { | |
113 LOG(WARNING) << "Skipping test because RSA-PSS is not supported"; | |
114 return; | |
115 } | |
116 | |
117 // Import public/private key pair. | |
118 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); | |
119 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); | |
120 | |
121 ImportRsaKeyPair( | |
122 HexStringToBytes(kPublicKeySpkiDerHex), | |
123 HexStringToBytes(kPrivateKeyPkcs8DerHex), | |
124 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaPss, | |
125 blink::WebCryptoAlgorithmIdSha1), | |
126 true, | |
127 blink::WebCryptoKeyUsageVerify, | |
128 blink::WebCryptoKeyUsageSign, | |
129 &public_key, | |
130 &private_key); | |
131 | |
132 // Zero-length salt. | |
133 blink::WebCryptoAlgorithm params = CreateRsaPssAlgorithm(0); | |
134 | |
135 // Some random message to sign. | |
136 std::vector<uint8_t> message = HexStringToBytes(kPublicKeySpkiDerHex); | |
137 | |
138 // Sign twice. | |
139 std::vector<uint8_t> signature1; | |
140 std::vector<uint8_t> signature2; | |
141 | |
142 ASSERT_EQ(Status::Success(), | |
143 Sign(params, private_key, CryptoData(message), &signature1)); | |
144 ASSERT_EQ(Status::Success(), | |
145 Sign(params, private_key, CryptoData(message), &signature2)); | |
146 | |
147 // The signatures will be the same this time. | |
148 EXPECT_EQ(CryptoData(signature1), CryptoData(signature2)); | |
149 | |
150 // Make sure that verification works. | |
151 bool is_match = false; | |
152 ASSERT_EQ(Status::Success(), | |
153 Verify(params, | |
154 public_key, | |
155 CryptoData(signature1), | |
156 CryptoData(message), | |
157 &is_match)); | |
158 EXPECT_TRUE(is_match); | |
159 | |
160 // Corrupt the signature and verification must fail. | |
161 ASSERT_EQ(Status::Success(), | |
162 Verify(params, | |
163 public_key, | |
164 CryptoData(Corrupted(signature2)), | |
165 CryptoData(message), | |
166 &is_match)); | |
167 EXPECT_FALSE(is_match); | |
168 } | |
169 | |
170 TEST(WebCryptoRsaPssTest, SignEmptyMessage) { | |
171 if (!SupportsRsaPss()) { | |
172 LOG(WARNING) << "Skipping test because RSA-PSS is not supported"; | |
173 return; | |
174 } | |
175 | |
176 // Import public/private key pair. | |
177 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); | |
178 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); | |
179 | |
180 ImportRsaKeyPair( | |
181 HexStringToBytes(kPublicKeySpkiDerHex), | |
182 HexStringToBytes(kPrivateKeyPkcs8DerHex), | |
183 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaPss, | |
184 blink::WebCryptoAlgorithmIdSha1), | |
185 true, | |
186 blink::WebCryptoKeyUsageVerify, | |
187 blink::WebCryptoKeyUsageSign, | |
188 &public_key, | |
189 &private_key); | |
190 | |
191 blink::WebCryptoAlgorithm params = CreateRsaPssAlgorithm(20); | |
192 std::vector<uint8_t> message; // Empty message. | |
193 | |
194 // Sign twice. | |
davidben
2014/10/19 03:42:34
Nit: This comment seems off.
eroman
2014/10/20 18:44:53
Done. (Copy paste error).
| |
195 std::vector<uint8_t> signature; | |
196 | |
197 ASSERT_EQ(Status::Success(), | |
198 Sign(params, private_key, CryptoData(message), &signature)); | |
199 | |
200 // Make sure that verification works. | |
201 bool is_match = false; | |
202 ASSERT_EQ(Status::Success(), | |
203 Verify(params, | |
204 public_key, | |
205 CryptoData(signature), | |
206 CryptoData(message), | |
207 &is_match)); | |
208 EXPECT_TRUE(is_match); | |
209 | |
210 // Corrupt the signature and verification must fail. | |
211 ASSERT_EQ(Status::Success(), | |
212 Verify(params, | |
213 public_key, | |
214 CryptoData(Corrupted(signature)), | |
215 CryptoData(message), | |
216 &is_match)); | |
217 EXPECT_FALSE(is_match); | |
218 } | |
219 | |
220 // Iterate through known answers and test verification. | |
221 // * Verify over original message should succeed | |
222 // * Verify over corrupted message should fail | |
223 // * Verification with corrupted signature should fail | |
224 TEST(WebCryptoRsaPssTest, VerifyKnownAnswer) { | |
225 if (!SupportsRsaPss()) { | |
226 LOG(WARNING) << "Skipping test because RSA-PSS is not supported"; | |
227 return; | |
228 } | |
229 | |
230 scoped_ptr<base::DictionaryValue> test_data; | |
231 ASSERT_TRUE(ReadJsonTestFileToDictionary("rsa_pss.json", &test_data)); | |
232 | |
233 const base::DictionaryValue* keys_dict = NULL; | |
234 ASSERT_TRUE(test_data->GetDictionary("keys", &keys_dict)); | |
235 | |
236 const base::ListValue* tests = NULL; | |
237 ASSERT_TRUE(test_data->GetList("tests", &tests)); | |
238 | |
239 for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) { | |
240 SCOPED_TRACE(test_index); | |
241 | |
242 const base::DictionaryValue* test; | |
243 ASSERT_TRUE(tests->GetDictionary(test_index, &test)); | |
244 | |
245 blink::WebCryptoAlgorithm hash = GetDigestAlgorithm(test, "hash"); | |
246 | |
247 std::string key_name; | |
248 ASSERT_TRUE(test->GetString("key", &key_name)); | |
249 | |
250 // Import the public key. | |
251 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); | |
252 std::vector<uint8_t> spki_bytes = | |
253 GetBytesFromHexString(keys_dict, key_name); | |
254 | |
255 ASSERT_EQ(Status::Success(), | |
256 ImportKey(blink::WebCryptoKeyFormatSpki, | |
257 CryptoData(spki_bytes), | |
258 CreateRsaHashedImportAlgorithm( | |
259 blink::WebCryptoAlgorithmIdRsaPss, hash.id()), | |
260 true, | |
261 blink::WebCryptoKeyUsageVerify, | |
262 &public_key)); | |
263 | |
264 int saltLength; | |
265 ASSERT_TRUE(test->GetInteger("saltLength", &saltLength)); | |
266 | |
267 std::vector<uint8_t> message = GetBytesFromHexString(test, "message"); | |
268 std::vector<uint8_t> signature = GetBytesFromHexString(test, "signature"); | |
269 | |
270 // Test that verification returns true when it should. | |
271 bool is_match = false; | |
272 ASSERT_EQ(Status::Success(), | |
273 Verify(CreateRsaPssAlgorithm(saltLength), | |
274 public_key, | |
275 CryptoData(signature), | |
276 CryptoData(message), | |
277 &is_match)); | |
278 EXPECT_TRUE(is_match); | |
279 | |
280 // Corrupt the message and make sure that verification fails. | |
281 ASSERT_EQ(Status::Success(), | |
282 Verify(CreateRsaPssAlgorithm(saltLength), | |
283 public_key, | |
284 CryptoData(signature), | |
285 CryptoData(Corrupted(message)), | |
286 &is_match)); | |
287 EXPECT_FALSE(is_match); | |
288 | |
289 // Corrupt the signature and make sure that verification fails. | |
290 ASSERT_EQ(Status::Success(), | |
291 Verify(CreateRsaPssAlgorithm(saltLength), | |
292 public_key, | |
293 CryptoData(Corrupted(signature)), | |
294 CryptoData(message), | |
295 &is_match)); | |
296 EXPECT_FALSE(is_match); | |
297 } | |
298 } | |
299 | |
300 } // namespace | |
301 | |
302 } // namespace webcrypto | |
303 | |
304 } // namespace content | |
OLD | NEW |