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, blink::WebCryptoKeyUsageVerify, blink::WebCryptoKeyUsageSign, | |
57 &public_key, &private_key); | |
58 | |
59 // Use a 20-byte length salt. | |
60 blink::WebCryptoAlgorithm params = CreateRsaPssAlgorithm(20); | |
61 | |
62 // Some random message to sign. | |
63 std::vector<uint8_t> message = HexStringToBytes(kPublicKeySpkiDerHex); | |
64 | |
65 // Sign twice. | |
66 std::vector<uint8_t> signature1; | |
67 std::vector<uint8_t> signature2; | |
68 | |
69 ASSERT_EQ(Status::Success(), | |
70 Sign(params, private_key, CryptoData(message), &signature1)); | |
71 ASSERT_EQ(Status::Success(), | |
72 Sign(params, private_key, CryptoData(message), &signature2)); | |
73 | |
74 // The signatures will be different because of the salt. | |
75 EXPECT_NE(CryptoData(signature1), CryptoData(signature2)); | |
76 | |
77 // However both signatures should work when verifying. | |
78 bool is_match = false; | |
79 | |
80 ASSERT_EQ(Status::Success(), | |
81 Verify(params, public_key, CryptoData(signature1), | |
82 CryptoData(message), &is_match)); | |
83 EXPECT_TRUE(is_match); | |
84 | |
85 ASSERT_EQ(Status::Success(), | |
86 Verify(params, public_key, CryptoData(signature2), | |
87 CryptoData(message), &is_match)); | |
88 EXPECT_TRUE(is_match); | |
89 | |
90 // Corrupt the signature and verification must fail. | |
91 ASSERT_EQ(Status::Success(), | |
92 Verify(params, public_key, CryptoData(Corrupted(signature2)), | |
93 CryptoData(message), &is_match)); | |
94 EXPECT_FALSE(is_match); | |
95 } | |
96 | |
97 // Try signing and verifying when the salt length is 0. The signature in this | |
98 // case is not random. | |
99 TEST(WebCryptoRsaPssTest, SignVerifyNoSalt) { | |
100 if (!SupportsRsaPss()) { | |
101 LOG(WARNING) << "Skipping test because RSA-PSS is not supported"; | |
102 return; | |
103 } | |
104 | |
105 // Import public/private key pair. | |
106 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); | |
107 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); | |
108 | |
109 ImportRsaKeyPair( | |
110 HexStringToBytes(kPublicKeySpkiDerHex), | |
111 HexStringToBytes(kPrivateKeyPkcs8DerHex), | |
112 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaPss, | |
113 blink::WebCryptoAlgorithmIdSha1), | |
114 true, blink::WebCryptoKeyUsageVerify, blink::WebCryptoKeyUsageSign, | |
115 &public_key, &private_key); | |
116 | |
117 // Zero-length salt. | |
118 blink::WebCryptoAlgorithm params = CreateRsaPssAlgorithm(0); | |
119 | |
120 // Some random message to sign. | |
121 std::vector<uint8_t> message = HexStringToBytes(kPublicKeySpkiDerHex); | |
122 | |
123 // Sign twice. | |
124 std::vector<uint8_t> signature1; | |
125 std::vector<uint8_t> signature2; | |
126 | |
127 ASSERT_EQ(Status::Success(), | |
128 Sign(params, private_key, CryptoData(message), &signature1)); | |
129 ASSERT_EQ(Status::Success(), | |
130 Sign(params, private_key, CryptoData(message), &signature2)); | |
131 | |
132 // The signatures will be the same this time. | |
133 EXPECT_EQ(CryptoData(signature1), CryptoData(signature2)); | |
134 | |
135 // Make sure that verification works. | |
136 bool is_match = false; | |
137 ASSERT_EQ(Status::Success(), | |
138 Verify(params, public_key, CryptoData(signature1), | |
139 CryptoData(message), &is_match)); | |
140 EXPECT_TRUE(is_match); | |
141 | |
142 // Corrupt the signature and verification must fail. | |
143 ASSERT_EQ(Status::Success(), | |
144 Verify(params, public_key, CryptoData(Corrupted(signature2)), | |
145 CryptoData(message), &is_match)); | |
146 EXPECT_FALSE(is_match); | |
147 } | |
148 | |
149 TEST(WebCryptoRsaPssTest, SignEmptyMessage) { | |
150 if (!SupportsRsaPss()) { | |
151 LOG(WARNING) << "Skipping test because RSA-PSS is not supported"; | |
152 return; | |
153 } | |
154 | |
155 // Import public/private key pair. | |
156 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); | |
157 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); | |
158 | |
159 ImportRsaKeyPair( | |
160 HexStringToBytes(kPublicKeySpkiDerHex), | |
161 HexStringToBytes(kPrivateKeyPkcs8DerHex), | |
162 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaPss, | |
163 blink::WebCryptoAlgorithmIdSha1), | |
164 true, blink::WebCryptoKeyUsageVerify, blink::WebCryptoKeyUsageSign, | |
165 &public_key, &private_key); | |
166 | |
167 blink::WebCryptoAlgorithm params = CreateRsaPssAlgorithm(20); | |
168 std::vector<uint8_t> message; // Empty message. | |
169 std::vector<uint8_t> signature; | |
170 | |
171 ASSERT_EQ(Status::Success(), | |
172 Sign(params, private_key, CryptoData(message), &signature)); | |
173 | |
174 // Make sure that verification works. | |
175 bool is_match = false; | |
176 ASSERT_EQ(Status::Success(), Verify(params, public_key, CryptoData(signature), | |
177 CryptoData(message), &is_match)); | |
178 EXPECT_TRUE(is_match); | |
179 | |
180 // Corrupt the signature and verification must fail. | |
181 ASSERT_EQ(Status::Success(), | |
182 Verify(params, public_key, CryptoData(Corrupted(signature)), | |
183 CryptoData(message), &is_match)); | |
184 EXPECT_FALSE(is_match); | |
185 } | |
186 | |
187 // Iterate through known answers and test verification. | |
188 // * Verify over original message should succeed | |
189 // * Verify over corrupted message should fail | |
190 // * Verification with corrupted signature should fail | |
191 TEST(WebCryptoRsaPssTest, VerifyKnownAnswer) { | |
192 if (!SupportsRsaPss()) { | |
193 LOG(WARNING) << "Skipping test because RSA-PSS is not supported"; | |
194 return; | |
195 } | |
196 | |
197 scoped_ptr<base::DictionaryValue> test_data; | |
198 ASSERT_TRUE(ReadJsonTestFileToDictionary("rsa_pss.json", &test_data)); | |
199 | |
200 const base::DictionaryValue* keys_dict = NULL; | |
201 ASSERT_TRUE(test_data->GetDictionary("keys", &keys_dict)); | |
202 | |
203 const base::ListValue* tests = NULL; | |
204 ASSERT_TRUE(test_data->GetList("tests", &tests)); | |
205 | |
206 for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) { | |
207 SCOPED_TRACE(test_index); | |
208 | |
209 const base::DictionaryValue* test; | |
210 ASSERT_TRUE(tests->GetDictionary(test_index, &test)); | |
211 | |
212 blink::WebCryptoAlgorithm hash = GetDigestAlgorithm(test, "hash"); | |
213 | |
214 std::string key_name; | |
215 ASSERT_TRUE(test->GetString("key", &key_name)); | |
216 | |
217 // Import the public key. | |
218 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); | |
219 std::vector<uint8_t> spki_bytes = | |
220 GetBytesFromHexString(keys_dict, key_name); | |
221 | |
222 ASSERT_EQ(Status::Success(), | |
223 ImportKey(blink::WebCryptoKeyFormatSpki, CryptoData(spki_bytes), | |
224 CreateRsaHashedImportAlgorithm( | |
225 blink::WebCryptoAlgorithmIdRsaPss, hash.id()), | |
226 true, blink::WebCryptoKeyUsageVerify, &public_key)); | |
227 | |
228 int saltLength; | |
229 ASSERT_TRUE(test->GetInteger("saltLength", &saltLength)); | |
230 | |
231 std::vector<uint8_t> message = GetBytesFromHexString(test, "message"); | |
232 std::vector<uint8_t> signature = GetBytesFromHexString(test, "signature"); | |
233 | |
234 // Test that verification returns true when it should. | |
235 bool is_match = false; | |
236 ASSERT_EQ(Status::Success(), | |
237 Verify(CreateRsaPssAlgorithm(saltLength), public_key, | |
238 CryptoData(signature), CryptoData(message), &is_match)); | |
239 EXPECT_TRUE(is_match); | |
240 | |
241 // Corrupt the message and make sure that verification fails. | |
242 ASSERT_EQ(Status::Success(), | |
243 Verify(CreateRsaPssAlgorithm(saltLength), public_key, | |
244 CryptoData(signature), CryptoData(Corrupted(message)), | |
245 &is_match)); | |
246 EXPECT_FALSE(is_match); | |
247 | |
248 // Corrupt the signature and make sure that verification fails. | |
249 ASSERT_EQ(Status::Success(), | |
250 Verify(CreateRsaPssAlgorithm(saltLength), public_key, | |
251 CryptoData(Corrupted(signature)), CryptoData(message), | |
252 &is_match)); | |
253 EXPECT_FALSE(is_match); | |
254 } | |
255 } | |
256 | |
257 } // namespace | |
258 | |
259 } // namespace webcrypto | |
260 | |
261 } // namespace content | |
OLD | NEW |