pk11_rsapss_unittest.cc (12005B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include <memory> 8 #include "nss.h" 9 #include "pk11pub.h" 10 #include "sechash.h" 11 #include "json_reader.h" 12 13 #include "databuffer.h" 14 15 #include "gtest/gtest.h" 16 #include "nss_scoped_ptrs.h" 17 18 #include "pk11_signature_test.h" 19 #include "pk11_rsapss_vectors.h" 20 #include "testvectors_base/test-structs.h" 21 22 namespace nss_test { 23 24 CK_MECHANISM_TYPE RsaPssMapCombo(SECOidTag hashOid) { 25 switch (hashOid) { 26 case SEC_OID_SHA1: 27 return CKM_SHA1_RSA_PKCS_PSS; 28 case SEC_OID_SHA224: 29 return CKM_SHA224_RSA_PKCS_PSS; 30 case SEC_OID_SHA256: 31 return CKM_SHA256_RSA_PKCS_PSS; 32 case SEC_OID_SHA384: 33 return CKM_SHA384_RSA_PKCS_PSS; 34 case SEC_OID_SHA512: 35 return CKM_SHA512_RSA_PKCS_PSS; 36 default: 37 break; 38 } 39 return CKM_INVALID_MECHANISM; 40 } 41 42 class Pkcs11RsaPssTestBase : public Pk11SignatureTest { 43 public: 44 Pkcs11RsaPssTestBase(SECOidTag hashOid, CK_RSA_PKCS_MGF_TYPE mgf, int sLen) 45 : Pk11SignatureTest(CKM_RSA_PKCS_PSS, hashOid, RsaPssMapCombo(hashOid)) { 46 pss_params_.hashAlg = PK11_AlgtagToMechanism(hashOid); 47 pss_params_.mgf = mgf; 48 pss_params_.sLen = sLen; 49 50 params_.type = siBuffer; 51 params_.data = reinterpret_cast<unsigned char*>(&pss_params_); 52 params_.len = sizeof(pss_params_); 53 } 54 55 const SECItem* parameters() const { return ¶ms_; } 56 57 void Verify(const RsaPssTestVector& vec) { 58 Pkcs11SignatureTestParams params = { 59 DataBuffer(), DataBuffer(vec.public_key.data(), vec.public_key.size()), 60 DataBuffer(vec.msg.data(), vec.msg.size()), 61 DataBuffer(vec.sig.data(), vec.sig.size())}; 62 63 Pk11SignatureTest::Verify(params, vec.valid); 64 } 65 66 private: 67 CK_RSA_PKCS_PSS_PARAMS pss_params_; 68 SECItem params_; 69 }; 70 71 class Pkcs11RsaPssTest : public Pkcs11RsaPssTestBase { 72 public: 73 Pkcs11RsaPssTest() 74 : Pkcs11RsaPssTestBase(SEC_OID_SHA1, CKG_MGF1_SHA1, SHA1_LENGTH) {} 75 }; 76 77 class Pkcs11RsaPssTestWycheproof : public ::testing::Test { 78 public: 79 struct TestVector { 80 uint64_t id; 81 std::vector<uint8_t> msg; 82 std::vector<uint8_t> sig; 83 bool valid; 84 }; 85 86 Pkcs11RsaPssTestWycheproof() {} 87 88 void Run(const std::string& file) { 89 WycheproofHeader("rsa_pss_" + file, "RSASSA-PSS", 90 "rsassa_pss_verify_schema.json", 91 [this](JsonReader& r) { RunGroup(r); }); 92 } 93 94 static void ReadTestAttr(TestVector& t, const std::string& n, JsonReader& r) { 95 if (n == "msg") { 96 t.msg = r.ReadHex(); 97 } else if (n == "sig") { 98 t.sig = r.ReadHex(); 99 } else { 100 FAIL() << "unknown key in test: " << n; 101 } 102 } 103 104 private: 105 class Pkcs11RsaPssTestWrap : public Pkcs11RsaPssTestBase { 106 public: 107 Pkcs11RsaPssTestWrap(SECOidTag hash, CK_RSA_PKCS_MGF_TYPE mgf, int s_len) 108 : Pkcs11RsaPssTestBase(hash, mgf, s_len) {} 109 110 void TestBody() {} 111 112 void Verify(const Pkcs11SignatureTestParams& params, bool valid) { 113 Pk11SignatureTest::Verify(params, valid); 114 } 115 }; 116 117 void RunTests(const std::vector<uint8_t>& public_key, SECOidTag hash, 118 CK_RSA_PKCS_MGF_TYPE mgf, int s_len, 119 const std::vector<TestVector>& tests) { 120 ASSERT_NE(0u, public_key.size()); 121 ASSERT_NE(SEC_OID_UNKNOWN, hash); 122 ASSERT_NE(CKM_INVALID_MECHANISM, mgf); 123 ASSERT_NE(0u, tests.size()); 124 125 for (auto& v : tests) { 126 std::cout << "Running tcid: " << v.id << std::endl; 127 128 Pkcs11RsaPssTestWrap test(hash, mgf, s_len); 129 Pkcs11SignatureTestParams params = { 130 DataBuffer(), DataBuffer(public_key.data(), public_key.size()), 131 DataBuffer(v.msg.data(), v.msg.size()), 132 DataBuffer(v.sig.data(), v.sig.size())}; 133 test.Verify(params, v.valid); 134 } 135 } 136 137 void RunGroup(JsonReader& r) { 138 std::vector<uint8_t> public_key; 139 SECOidTag hash = SEC_OID_UNKNOWN; 140 CK_RSA_PKCS_MGF_TYPE mgf = CKM_INVALID_MECHANISM; 141 int s_len = 0; 142 std::vector<TestVector> tests; 143 while (r.NextItem()) { 144 std::string n = r.ReadLabel(); 145 if (n == "") { 146 break; 147 } 148 if (n == "e" || n == "keyAsn" || n == "keyPem" || n == "n") { 149 (void)r.ReadString(); 150 } else if (n == "keyDer") { 151 public_key = r.ReadHex(); 152 } else if (n == "keysize") { 153 (void)r.ReadInt(); 154 } else if (n == "mgf") { 155 std::string s = r.ReadString(); 156 ASSERT_EQ(s, "MGF1"); 157 } else if (n == "mgfSha") { 158 std::string s = r.ReadString(); 159 if (s == "SHA-1") { 160 mgf = CKG_MGF1_SHA1; 161 } else if (s == "SHA-224") { 162 mgf = CKG_MGF1_SHA224; 163 } else if (s == "SHA-256") { 164 mgf = CKG_MGF1_SHA256; 165 } else if (s == "SHA-384") { 166 mgf = CKG_MGF1_SHA384; 167 } else if (s == "SHA-512") { 168 mgf = CKG_MGF1_SHA512; 169 } else { 170 FAIL() << "unsupported MGF hash"; 171 } 172 } else if (n == "sLen") { 173 s_len = static_cast<unsigned int>(r.ReadInt()); 174 } else if (n == "sha") { 175 std::string s = r.ReadString(); 176 if (s == "SHA-1") { 177 hash = SEC_OID_SHA1; 178 } else if (s == "SHA-224") { 179 hash = SEC_OID_SHA224; 180 } else if (s == "SHA-256") { 181 hash = SEC_OID_SHA256; 182 } else if (s == "SHA-384") { 183 hash = SEC_OID_SHA384; 184 } else if (s == "SHA-512") { 185 hash = SEC_OID_SHA512; 186 } else { 187 FAIL() << "unsupported hash"; 188 } 189 } else if (n == "type") { 190 ASSERT_EQ("RsassaPssVerify", r.ReadString()); 191 } else if (n == "tests") { 192 WycheproofReadTests(r, &tests, ReadTestAttr); 193 } else { 194 FAIL() << "unknown test group attribute: " << n; 195 } 196 } 197 198 RunTests(public_key, hash, mgf, s_len, tests); 199 } 200 }; 201 202 TEST_F(Pkcs11RsaPssTest, GenerateAndSignAndVerify) { 203 // Sign data with a 1024-bit RSA key, using PSS/SHA-256. 204 SECOidTag hashOid = SEC_OID_SHA256; 205 CK_MECHANISM_TYPE hash_mech = CKM_SHA256; 206 CK_RSA_PKCS_MGF_TYPE mgf = CKG_MGF1_SHA256; 207 PK11RSAGenParams rsaGenParams = {1024, 0x10001}; 208 209 // Generate RSA key pair. 210 ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); 211 SECKEYPublicKey* pub_keyRaw = nullptr; 212 ScopedSECKEYPrivateKey privKey( 213 PK11_GenerateKeyPair(slot.get(), CKM_RSA_PKCS_KEY_PAIR_GEN, &rsaGenParams, 214 &pub_keyRaw, false, false, nullptr)); 215 ASSERT_TRUE(!!privKey && pub_keyRaw); 216 ScopedSECKEYPublicKey pub_key(pub_keyRaw); 217 218 // Generate random data to sign. 219 uint8_t dataBuf[50]; 220 SECItem data = {siBuffer, dataBuf, sizeof(dataBuf)}; 221 unsigned int hLen = HASH_ResultLenByOidTag(hashOid); 222 SECStatus rv = PK11_GenerateRandomOnSlot(slot.get(), data.data, data.len); 223 EXPECT_EQ(rv, SECSuccess); 224 225 // Allocate memory for the signature. 226 std::vector<uint8_t> sigBuf(PK11_SignatureLen(privKey.get())); 227 SECItem sig = {siBuffer, &sigBuf[0], 228 static_cast<unsigned int>(sigBuf.size())}; 229 230 // Set up PSS parameters. 231 CK_RSA_PKCS_PSS_PARAMS pss_params = {hash_mech, mgf, hLen}; 232 SECItem params = {siBuffer, reinterpret_cast<unsigned char*>(&pss_params), 233 sizeof(pss_params)}; 234 235 // Sign. 236 rv = PK11_SignWithMechanism(privKey.get(), mechanism(), ¶ms, &sig, &data); 237 EXPECT_EQ(rv, SECSuccess); 238 239 // Verify. 240 rv = PK11_VerifyWithMechanism(pub_key.get(), mechanism(), ¶ms, &sig, 241 &data, nullptr); 242 EXPECT_EQ(rv, SECSuccess); 243 244 // Verification with modified data must fail. 245 data.data[0] ^= 0xff; 246 rv = PK11_VerifyWithMechanism(pub_key.get(), mechanism(), ¶ms, &sig, 247 &data, nullptr); 248 EXPECT_EQ(rv, SECFailure); 249 250 // Verification with original data but the wrong signature must fail. 251 data.data[0] ^= 0xff; // Revert previous changes. 252 sig.data[0] ^= 0xff; 253 rv = PK11_VerifyWithMechanism(pub_key.get(), mechanism(), ¶ms, &sig, 254 &data, nullptr); 255 EXPECT_EQ(rv, SECFailure); 256 } 257 258 TEST_F(Pkcs11RsaPssTest, NoLeakWithInvalidExponent) { 259 // Attempt to generate an RSA key with a public exponent of 1. This should 260 // fail, but it shouldn't leak memory. 261 PK11RSAGenParams rsaGenParams = {1024, 0x01}; 262 263 // Generate RSA key pair. 264 ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); 265 SECKEYPublicKey* pub_key = nullptr; 266 SECKEYPrivateKey* privKey = 267 PK11_GenerateKeyPair(slot.get(), CKM_RSA_PKCS_KEY_PAIR_GEN, &rsaGenParams, 268 &pub_key, false, false, nullptr); 269 EXPECT_FALSE(privKey); 270 EXPECT_FALSE(pub_key); 271 } 272 class Pkcs11RsaPssVectorTest 273 : public Pkcs11RsaPssTest, 274 public ::testing::WithParamInterface<Pkcs11SignatureTestParams> {}; 275 276 TEST_P(Pkcs11RsaPssVectorTest, Verify) { 277 Pk11SignatureTest::Verify(GetParam()); 278 } 279 280 TEST_P(Pkcs11RsaPssVectorTest, SignAndVerify) { SignAndVerify(GetParam()); } 281 282 #define VECTOR(pkcs8, spki, data, sig) \ 283 { \ 284 DataBuffer(pkcs8, sizeof(pkcs8)), DataBuffer(spki, sizeof(spki)), \ 285 DataBuffer(data, sizeof(data)), DataBuffer(sig, sizeof(sig)) \ 286 } 287 #define VECTOR_N(n) \ 288 VECTOR(kTestVector##n##Pkcs8, kTestVector##n##Spki, kTestVector##n##Data, \ 289 kTestVector##n##Sig) 290 291 static const Pkcs11SignatureTestParams kRsaPssVectors[] = { 292 // RSA-PSS test vectors, pss-vect.txt, Example 1.1: A 1024-bit RSA Key Pair 293 // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip> 294 VECTOR_N(1), 295 // RSA-PSS test vectors, pss-vect.txt, Example 2.1: A 1025-bit RSA Key Pair 296 // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip> 297 VECTOR_N(2), 298 // RSA-PSS test vectors, pss-vect.txt, Example 3.1: A 1026-bit RSA Key Pair 299 // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip> 300 VECTOR_N(3), 301 // RSA-PSS test vectors, pss-vect.txt, Example 4.1: A 1027-bit RSA Key Pair 302 // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip> 303 VECTOR_N(4), 304 // RSA-PSS test vectors, pss-vect.txt, Example 5.1: A 1028-bit RSA Key Pair 305 // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip> 306 VECTOR_N(5), 307 // RSA-PSS test vectors, pss-vect.txt, Example 6.1: A 1029-bit RSA Key Pair 308 // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip> 309 VECTOR_N(6), 310 // RSA-PSS test vectors, pss-vect.txt, Example 7.1: A 1030-bit RSA Key Pair 311 // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip> 312 VECTOR_N(7), 313 // RSA-PSS test vectors, pss-vect.txt, Example 8.1: A 1031-bit RSA Key Pair 314 // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip> 315 VECTOR_N(8), 316 // RSA-PSS test vectors, pss-vect.txt, Example 9.1: A 1536-bit RSA Key Pair 317 // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip> 318 VECTOR_N(9), 319 // RSA-PSS test vectors, pss-vect.txt, Example 10.1: A 2048-bit RSA Key Pair 320 // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip> 321 VECTOR_N(10)}; 322 323 INSTANTIATE_TEST_SUITE_P(RsaPssSignVerify, Pkcs11RsaPssVectorTest, 324 ::testing::ValuesIn(kRsaPssVectors)); 325 326 TEST_F(Pkcs11RsaPssTestWycheproof, RsaPss2048Sha1) { Run("2048_sha1_mgf1_20"); } 327 TEST_F(Pkcs11RsaPssTestWycheproof, RsaPss2048Sha256_0) { 328 Run("2048_sha256_mgf1_0"); 329 } 330 TEST_F(Pkcs11RsaPssTestWycheproof, RsaPss2048Sha256_32) { 331 Run("2048_sha256_mgf1_32"); 332 } 333 TEST_F(Pkcs11RsaPssTestWycheproof, RsaPss3072Sha256) { 334 Run("3072_sha256_mgf1_32"); 335 } 336 TEST_F(Pkcs11RsaPssTestWycheproof, RsaPss4096Sha256) { 337 Run("4096_sha256_mgf1_32"); 338 } 339 TEST_F(Pkcs11RsaPssTestWycheproof, RsaPss4096Sha512) { 340 Run("4096_sha512_mgf1_32"); 341 } 342 TEST_F(Pkcs11RsaPssTestWycheproof, RsaPssMisc) { Run("misc"); } 343 344 } // namespace nss_test