blob: 8e313bc5a73fcc9a187aaae9818f35b38746a9dc [file] [log] [blame]
eroman8793ece2014-10-20 20:47:151// 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
avi5dd91f82015-12-25 22:30:465#include <stddef.h>
6#include <stdint.h>
7
erg56f12322015-04-17 00:51:488#include "components/webcrypto/algorithm_dispatch.h"
eroman7bcd6a72015-09-16 02:41:219#include "components/webcrypto/algorithms/test_helpers.h"
erg56f12322015-04-17 00:51:4810#include "components/webcrypto/crypto_data.h"
11#include "components/webcrypto/jwk.h"
12#include "components/webcrypto/status.h"
eroman8793ece2014-10-20 20:47:1513#include "testing/gtest/include/gtest/gtest.h"
Blink Reformata30d4232018-04-07 15:31:0614#include "third_party/blink/public/platform/web_crypto_algorithm_params.h"
15#include "third_party/blink/public/platform/web_crypto_key.h"
16#include "third_party/blink/public/platform/web_crypto_key_algorithm.h"
eroman8793ece2014-10-20 20:47:1517
eroman8793ece2014-10-20 20:47:1518namespace webcrypto {
19
20namespace {
21
eroman8793ece2014-10-20 20:47:1522blink::WebCryptoAlgorithm CreateRsaPssAlgorithm(
23 unsigned int salt_length_bytes) {
Blink Reformat1c4d759e2017-04-09 16:34:5424 return blink::WebCryptoAlgorithm::AdoptParamsAndCreate(
25 blink::kWebCryptoAlgorithmIdRsaPss,
eroman8793ece2014-10-20 20:47:1526 new blink::WebCryptoRsaPssParams(salt_length_bytes));
27}
28
bashi68ded772015-09-06 04:35:0529class WebCryptoRsaPssTest : public WebCryptoTestBase {};
30
eroman8793ece2014-10-20 20:47:1531// Test that no two RSA-PSS signatures are identical, when using a non-zero
32// lengthed salt.
bashi68ded772015-09-06 04:35:0533TEST_F(WebCryptoRsaPssTest, SignIsRandom) {
eroman8793ece2014-10-20 20:47:1534 // Import public/private key pair.
Blink Reformat1c4d759e2017-04-09 16:34:5435 blink::WebCryptoKey public_key = blink::WebCryptoKey::CreateNull();
36 blink::WebCryptoKey private_key = blink::WebCryptoKey::CreateNull();
eroman8793ece2014-10-20 20:47:1537
38 ImportRsaKeyPair(
39 HexStringToBytes(kPublicKeySpkiDerHex),
40 HexStringToBytes(kPrivateKeyPkcs8DerHex),
Blink Reformat1c4d759e2017-04-09 16:34:5441 CreateRsaHashedImportAlgorithm(blink::kWebCryptoAlgorithmIdRsaPss,
42 blink::kWebCryptoAlgorithmIdSha1),
43 true, blink::kWebCryptoKeyUsageVerify, blink::kWebCryptoKeyUsageSign,
eroman38bb4bd2014-11-24 23:47:0644 &public_key, &private_key);
eroman8793ece2014-10-20 20:47:1545
46 // Use a 20-byte length salt.
47 blink::WebCryptoAlgorithm params = CreateRsaPssAlgorithm(20);
48
49 // Some random message to sign.
50 std::vector<uint8_t> message = HexStringToBytes(kPublicKeySpkiDerHex);
51
52 // Sign twice.
53 std::vector<uint8_t> signature1;
54 std::vector<uint8_t> signature2;
55
56 ASSERT_EQ(Status::Success(),
57 Sign(params, private_key, CryptoData(message), &signature1));
58 ASSERT_EQ(Status::Success(),
59 Sign(params, private_key, CryptoData(message), &signature2));
60
61 // The signatures will be different because of the salt.
62 EXPECT_NE(CryptoData(signature1), CryptoData(signature2));
63
64 // However both signatures should work when verifying.
65 bool is_match = false;
66
67 ASSERT_EQ(Status::Success(),
eroman38bb4bd2014-11-24 23:47:0668 Verify(params, public_key, CryptoData(signature1),
69 CryptoData(message), &is_match));
eroman8793ece2014-10-20 20:47:1570 EXPECT_TRUE(is_match);
71
72 ASSERT_EQ(Status::Success(),
eroman38bb4bd2014-11-24 23:47:0673 Verify(params, public_key, CryptoData(signature2),
74 CryptoData(message), &is_match));
eroman8793ece2014-10-20 20:47:1575 EXPECT_TRUE(is_match);
76
77 // Corrupt the signature and verification must fail.
78 ASSERT_EQ(Status::Success(),
eroman38bb4bd2014-11-24 23:47:0679 Verify(params, public_key, CryptoData(Corrupted(signature2)),
80 CryptoData(message), &is_match));
eroman8793ece2014-10-20 20:47:1581 EXPECT_FALSE(is_match);
82}
83
84// Try signing and verifying when the salt length is 0. The signature in this
85// case is not random.
bashi68ded772015-09-06 04:35:0586TEST_F(WebCryptoRsaPssTest, SignVerifyNoSalt) {
eroman8793ece2014-10-20 20:47:1587 // Import public/private key pair.
Blink Reformat1c4d759e2017-04-09 16:34:5488 blink::WebCryptoKey public_key = blink::WebCryptoKey::CreateNull();
89 blink::WebCryptoKey private_key = blink::WebCryptoKey::CreateNull();
eroman8793ece2014-10-20 20:47:1590
91 ImportRsaKeyPair(
92 HexStringToBytes(kPublicKeySpkiDerHex),
93 HexStringToBytes(kPrivateKeyPkcs8DerHex),
Blink Reformat1c4d759e2017-04-09 16:34:5494 CreateRsaHashedImportAlgorithm(blink::kWebCryptoAlgorithmIdRsaPss,
95 blink::kWebCryptoAlgorithmIdSha1),
96 true, blink::kWebCryptoKeyUsageVerify, blink::kWebCryptoKeyUsageSign,
eroman38bb4bd2014-11-24 23:47:0697 &public_key, &private_key);
eroman8793ece2014-10-20 20:47:1598
99 // Zero-length salt.
100 blink::WebCryptoAlgorithm params = CreateRsaPssAlgorithm(0);
101
102 // Some random message to sign.
103 std::vector<uint8_t> message = HexStringToBytes(kPublicKeySpkiDerHex);
104
105 // Sign twice.
106 std::vector<uint8_t> signature1;
107 std::vector<uint8_t> signature2;
108
109 ASSERT_EQ(Status::Success(),
110 Sign(params, private_key, CryptoData(message), &signature1));
111 ASSERT_EQ(Status::Success(),
112 Sign(params, private_key, CryptoData(message), &signature2));
113
114 // The signatures will be the same this time.
115 EXPECT_EQ(CryptoData(signature1), CryptoData(signature2));
116
117 // Make sure that verification works.
118 bool is_match = false;
119 ASSERT_EQ(Status::Success(),
eroman38bb4bd2014-11-24 23:47:06120 Verify(params, public_key, CryptoData(signature1),
121 CryptoData(message), &is_match));
eroman8793ece2014-10-20 20:47:15122 EXPECT_TRUE(is_match);
123
124 // Corrupt the signature and verification must fail.
125 ASSERT_EQ(Status::Success(),
eroman38bb4bd2014-11-24 23:47:06126 Verify(params, public_key, CryptoData(Corrupted(signature2)),
127 CryptoData(message), &is_match));
eroman8793ece2014-10-20 20:47:15128 EXPECT_FALSE(is_match);
129}
130
bashi68ded772015-09-06 04:35:05131TEST_F(WebCryptoRsaPssTest, SignEmptyMessage) {
eroman8793ece2014-10-20 20:47:15132 // Import public/private key pair.
Blink Reformat1c4d759e2017-04-09 16:34:54133 blink::WebCryptoKey public_key = blink::WebCryptoKey::CreateNull();
134 blink::WebCryptoKey private_key = blink::WebCryptoKey::CreateNull();
eroman8793ece2014-10-20 20:47:15135
136 ImportRsaKeyPair(
137 HexStringToBytes(kPublicKeySpkiDerHex),
138 HexStringToBytes(kPrivateKeyPkcs8DerHex),
Blink Reformat1c4d759e2017-04-09 16:34:54139 CreateRsaHashedImportAlgorithm(blink::kWebCryptoAlgorithmIdRsaPss,
140 blink::kWebCryptoAlgorithmIdSha1),
141 true, blink::kWebCryptoKeyUsageVerify, blink::kWebCryptoKeyUsageSign,
eroman38bb4bd2014-11-24 23:47:06142 &public_key, &private_key);
eroman8793ece2014-10-20 20:47:15143
144 blink::WebCryptoAlgorithm params = CreateRsaPssAlgorithm(20);
145 std::vector<uint8_t> message; // Empty message.
146 std::vector<uint8_t> signature;
147
148 ASSERT_EQ(Status::Success(),
149 Sign(params, private_key, CryptoData(message), &signature));
150
151 // Make sure that verification works.
152 bool is_match = false;
eroman38bb4bd2014-11-24 23:47:06153 ASSERT_EQ(Status::Success(), Verify(params, public_key, CryptoData(signature),
154 CryptoData(message), &is_match));
eroman8793ece2014-10-20 20:47:15155 EXPECT_TRUE(is_match);
156
157 // Corrupt the signature and verification must fail.
158 ASSERT_EQ(Status::Success(),
eroman38bb4bd2014-11-24 23:47:06159 Verify(params, public_key, CryptoData(Corrupted(signature)),
160 CryptoData(message), &is_match));
eroman8793ece2014-10-20 20:47:15161 EXPECT_FALSE(is_match);
162}
163
164// Iterate through known answers and test verification.
165// * Verify over original message should succeed
166// * Verify over corrupted message should fail
167// * Verification with corrupted signature should fail
bashi68ded772015-09-06 04:35:05168TEST_F(WebCryptoRsaPssTest, VerifyKnownAnswer) {
Sylvain Defresnee105c8f62019-02-19 17:53:27169 base::DictionaryValue test_data;
eroman8793ece2014-10-20 20:47:15170 ASSERT_TRUE(ReadJsonTestFileToDictionary("rsa_pss.json", &test_data));
171
Ivan Kotenkov75b1c3a2017-10-24 14:47:24172 const base::DictionaryValue* keys_dict = nullptr;
Sylvain Defresnee105c8f62019-02-19 17:53:27173 ASSERT_TRUE(test_data.GetDictionary("keys", &keys_dict));
eroman8793ece2014-10-20 20:47:15174
Ivan Kotenkov75b1c3a2017-10-24 14:47:24175 const base::ListValue* tests = nullptr;
Sylvain Defresnee105c8f62019-02-19 17:53:27176 ASSERT_TRUE(test_data.GetList("tests", &tests));
eroman8793ece2014-10-20 20:47:15177
178 for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
179 SCOPED_TRACE(test_index);
180
181 const base::DictionaryValue* test;
182 ASSERT_TRUE(tests->GetDictionary(test_index, &test));
183
184 blink::WebCryptoAlgorithm hash = GetDigestAlgorithm(test, "hash");
185
186 std::string key_name;
187 ASSERT_TRUE(test->GetString("key", &key_name));
188
189 // Import the public key.
Blink Reformat1c4d759e2017-04-09 16:34:54190 blink::WebCryptoKey public_key = blink::WebCryptoKey::CreateNull();
eroman8793ece2014-10-20 20:47:15191 std::vector<uint8_t> spki_bytes =
192 GetBytesFromHexString(keys_dict, key_name);
193
194 ASSERT_EQ(Status::Success(),
Blink Reformat1c4d759e2017-04-09 16:34:54195 ImportKey(blink::kWebCryptoKeyFormatSpki, CryptoData(spki_bytes),
eroman8793ece2014-10-20 20:47:15196 CreateRsaHashedImportAlgorithm(
Blink Reformat1c4d759e2017-04-09 16:34:54197 blink::kWebCryptoAlgorithmIdRsaPss, hash.Id()),
198 true, blink::kWebCryptoKeyUsageVerify, &public_key));
eroman8793ece2014-10-20 20:47:15199
200 int saltLength;
201 ASSERT_TRUE(test->GetInteger("saltLength", &saltLength));
202
203 std::vector<uint8_t> message = GetBytesFromHexString(test, "message");
204 std::vector<uint8_t> signature = GetBytesFromHexString(test, "signature");
205
206 // Test that verification returns true when it should.
207 bool is_match = false;
208 ASSERT_EQ(Status::Success(),
eroman38bb4bd2014-11-24 23:47:06209 Verify(CreateRsaPssAlgorithm(saltLength), public_key,
210 CryptoData(signature), CryptoData(message), &is_match));
eroman8793ece2014-10-20 20:47:15211 EXPECT_TRUE(is_match);
212
213 // Corrupt the message and make sure that verification fails.
214 ASSERT_EQ(Status::Success(),
eroman38bb4bd2014-11-24 23:47:06215 Verify(CreateRsaPssAlgorithm(saltLength), public_key,
216 CryptoData(signature), CryptoData(Corrupted(message)),
eroman8793ece2014-10-20 20:47:15217 &is_match));
218 EXPECT_FALSE(is_match);
219
220 // Corrupt the signature and make sure that verification fails.
221 ASSERT_EQ(Status::Success(),
eroman38bb4bd2014-11-24 23:47:06222 Verify(CreateRsaPssAlgorithm(saltLength), public_key,
223 CryptoData(Corrupted(signature)), CryptoData(message),
eroman8793ece2014-10-20 20:47:15224 &is_match));
225 EXPECT_FALSE(is_match);
226 }
227}
228
229} // namespace
230
231} // namespace webcrypto