diff --git a/automation/abi-check/expected-report-libnss3.so.txt b/automation/abi-check/expected-report-libnss3.so.txt index e69de29bb2..f4cb8919da 100644 --- a/automation/abi-check/expected-report-libnss3.so.txt +++ b/automation/abi-check/expected-report-libnss3.so.txt @@ -0,0 +1,15 @@ + +2 Added functions: + + 'function PK11Context* PK11_CreateContextByPrivKey(CK_MECHANISM_TYPE, CK_ATTRIBUTE_TYPE, SECKEYPrivateKey*, const SECItem*)' {PK11_CreateContextByPrivKey@@NSS_3.64} + 'function PK11Context* PK11_CreateContextByPubKey(CK_MECHANISM_TYPE, CK_ATTRIBUTE_TYPE, SECKEYPublicKey*, const SECItem*, void*)' {PK11_CreateContextByPubKey@@NSS_3.64} + +1 function with some indirect sub-type change: + + [C]'function PK11Context* PK11_CreateContextBySymKey(CK_MECHANISM_TYPE, CK_ATTRIBUTE_TYPE, PK11SymKey*, SECItem*)' at pk11cxt.c:479:1 has some indirect sub-type changes: + parameter 4 of type 'SECItem*' changed: + in pointed to type 'typedef SECItem': + entity changed from 'typedef SECItem' to 'const SECItem' + type size hasn't changed + + diff --git a/gtests/pk11_gtest/manifest.mn b/gtests/pk11_gtest/manifest.mn index 80530675b3..a1a1af346e 100644 --- a/gtests/pk11_gtest/manifest.mn +++ b/gtests/pk11_gtest/manifest.mn @@ -38,6 +38,7 @@ CPPSRCS = \ pk11_rsaoaep_unittest.cc \ pk11_rsapkcs1_unittest.cc \ pk11_rsapss_unittest.cc \ + pk11_signature_test.cc \ pk11_seed_cbc_unittest.cc \ $(NULL) diff --git a/gtests/pk11_gtest/pk11_dsa_unittest.cc b/gtests/pk11_gtest/pk11_dsa_unittest.cc index 0c776c9f1d..634d496bf0 100644 --- a/gtests/pk11_gtest/pk11_dsa_unittest.cc +++ b/gtests/pk11_gtest/pk11_dsa_unittest.cc @@ -6,12 +6,14 @@ #include #include "nss.h" +#include "prerror.h" #include "pk11pub.h" #include "sechash.h" #include "cryptohi.h" #include "cpputil.h" #include "databuffer.h" +#include "pk11_signature_test.h" #include "gtest/gtest.h" #include "nss_scoped_ptrs.h" @@ -19,59 +21,59 @@ #include "testvectors/dsa-vectors.h" namespace nss_test { - -class Pkcs11DsaTest : public ::testing::TestWithParam { +CK_MECHANISM_TYPE +DsaHashToComboMech(SECOidTag hash) { + switch (hash) { + case SEC_OID_SHA1: + return CKM_DSA_SHA1; + case SEC_OID_SHA224: + return CKM_DSA_SHA224; + case SEC_OID_SHA256: + return CKM_DSA_SHA256; + case SEC_OID_SHA384: + return CKM_DSA_SHA384; + case SEC_OID_SHA512: + return CKM_DSA_SHA512; + default: + break; + } + return CKM_INVALID_MECHANISM; +} + +class Pkcs11DsaTestBase : public Pk11SignatureTest { protected: - void Derive(const uint8_t* sig, size_t sig_len, const uint8_t* spki, - size_t spki_len, const uint8_t* data, size_t data_len, - bool expect_success, const uint32_t test_id, - const SECOidTag hash_oid) { - std::stringstream s; - s << "Test with original ID #" << test_id << " failed.\n"; - s << "Expected Success: " << expect_success << "\n"; - std::string msg = s.str(); - - SECItem spki_item = {siBuffer, toUcharPtr(spki), - static_cast(spki_len)}; - - ScopedCERTSubjectPublicKeyInfo cert_spki( - SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item)); - ASSERT_TRUE(cert_spki) << msg; - - ScopedSECKEYPublicKey pub_key(SECKEY_ExtractPublicKey(cert_spki.get())); - ASSERT_TRUE(pub_key) << msg; - - SECItem sig_item = {siBuffer, toUcharPtr(sig), - static_cast(sig_len)}; - ScopedSECItem decoded_sig_item( - DSAU_DecodeDerSigToLen(&sig_item, SECKEY_SignatureLen(pub_key.get()))); - if (!decoded_sig_item) { - ASSERT_FALSE(expect_success) << msg; + Pkcs11DsaTestBase(SECOidTag hashOid) + : Pk11SignatureTest(CKM_DSA, hashOid, DsaHashToComboMech(hashOid)) {} + + void Verify(const DsaTestVector vec) { + /* DSA vectors encode the signature in DER, we need to unwrap it before + * we can send the raw signatures to PKCS #11. */ + DataBuffer pubKeyBuffer(vec.public_key.data(), vec.public_key.size()); + ScopedSECKEYPublicKey nssPubKey(ImportPublicKey(pubKeyBuffer)); + SECItem sigItem = {siBuffer, toUcharPtr(vec.sig.data()), + static_cast(vec.sig.size())}; + ScopedSECItem decodedSigItem( + DSAU_DecodeDerSigToLen(&sigItem, SECKEY_SignatureLen(nssPubKey.get()))); + if (!decodedSigItem) { + ASSERT_FALSE(vec.valid) << "Failed to decode DSA signature Error: " + << PORT_ErrorToString(PORT_GetError()) << "\n"; return; } - DataBuffer hash; - hash.Allocate(static_cast(HASH_ResultLenByOidTag(hash_oid))); - SECStatus rv = PK11_HashBuf(hash_oid, toUcharPtr(hash.data()), - toUcharPtr(data), data_len); - ASSERT_EQ(SECSuccess, rv) << msg; - - // Verify. - SECItem hash_item = {siBuffer, toUcharPtr(hash.data()), - static_cast(hash.len())}; - rv = PK11_VerifyWithMechanism(pub_key.get(), CKM_DSA, nullptr, - decoded_sig_item.get(), &hash_item, nullptr); - EXPECT_EQ(expect_success ? SECSuccess : SECFailure, rv); - }; + Pkcs11SignatureTestParams params = { + DataBuffer(), pubKeyBuffer, DataBuffer(vec.msg.data(), vec.msg.size()), + DataBuffer(decodedSigItem.get()->data, decodedSigItem.get()->len)}; + Pk11SignatureTest::Verify(params, (bool)vec.valid); + } +}; - void Derive(const DsaTestVector vector) { - Derive(vector.sig.data(), vector.sig.size(), vector.public_key.data(), - vector.public_key.size(), vector.msg.data(), vector.msg.size(), - vector.valid, vector.id, vector.hash_oid); - }; +class Pkcs11DsaTest : public Pkcs11DsaTestBase, + public ::testing::WithParamInterface { + public: + Pkcs11DsaTest() : Pkcs11DsaTestBase(GetParam().hash_oid) {} }; -TEST_P(Pkcs11DsaTest, WycheproofVectors) { Derive(GetParam()); } +TEST_P(Pkcs11DsaTest, WycheproofVectors) { Verify(GetParam()); } INSTANTIATE_TEST_SUITE_P(DsaTest, Pkcs11DsaTest, ::testing::ValuesIn(kDsaWycheproofVectors)); diff --git a/gtests/pk11_gtest/pk11_ecdsa_unittest.cc b/gtests/pk11_gtest/pk11_ecdsa_unittest.cc index c127004c8f..9f4bf6a2b5 100644 --- a/gtests/pk11_gtest/pk11_ecdsa_unittest.cc +++ b/gtests/pk11_gtest/pk11_ecdsa_unittest.cc @@ -8,6 +8,7 @@ #include "sechash.h" #include "cryptohi.h" +#include "cpputil.h" #include "gtest/gtest.h" #include "nss_scoped_ptrs.h" @@ -19,10 +20,29 @@ namespace nss_test { +CK_MECHANISM_TYPE +EcHashToComboMech(SECOidTag hash) { + switch (hash) { + case SEC_OID_SHA1: + return CKM_ECDSA_SHA1; + case SEC_OID_SHA224: + return CKM_ECDSA_SHA224; + case SEC_OID_SHA256: + return CKM_ECDSA_SHA256; + case SEC_OID_SHA384: + return CKM_ECDSA_SHA384; + case SEC_OID_SHA512: + return CKM_ECDSA_SHA512; + default: + break; + } + return CKM_INVALID_MECHANISM; +} + class Pkcs11EcdsaTestBase : public Pk11SignatureTest { protected: Pkcs11EcdsaTestBase(SECOidTag hash_oid) - : Pk11SignatureTest(CKM_ECDSA, hash_oid) {} + : Pk11SignatureTest(CKM_ECDSA, hash_oid, EcHashToComboMech(hash_oid)) {} }; struct Pkcs11EcdsaTestParams { @@ -88,7 +108,8 @@ TEST_F(Pkcs11EcdsaSha256Test, ImportOnlyAlgorithmParams) { sizeof(kP256Pkcs8OnlyAlgorithmParams)); DataBuffer data(kP256Data, sizeof(kP256Data)); DataBuffer sig; - EXPECT_TRUE(ImportPrivateKeyAndSignHashedData(k, data, &sig)); + DataBuffer sig2; + EXPECT_TRUE(ImportPrivateKeyAndSignHashedData(k, data, &sig, &sig2)); }; // Importing a private key in PKCS#8 format must succeed when the outer AlgID @@ -99,7 +120,8 @@ TEST_F(Pkcs11EcdsaSha256Test, ImportMatchingCurveOIDAndAlgorithmParams) { sizeof(kP256Pkcs8MatchingCurveOIDAndAlgorithmParams)); DataBuffer data(kP256Data, sizeof(kP256Data)); DataBuffer sig; - EXPECT_TRUE(ImportPrivateKeyAndSignHashedData(k, data, &sig)); + DataBuffer sig2; + EXPECT_TRUE(ImportPrivateKeyAndSignHashedData(k, data, &sig, &sig2)); }; // Importing a private key in PKCS#8 format must succeed when the outer AlgID @@ -110,7 +132,8 @@ TEST_F(Pkcs11EcdsaSha256Test, ImportDissimilarCurveOIDAndAlgorithmParams) { sizeof(kP256Pkcs8DissimilarCurveOIDAndAlgorithmParams)); DataBuffer data(kP256Data, sizeof(kP256Data)); DataBuffer sig; - EXPECT_TRUE(ImportPrivateKeyAndSignHashedData(k, data, &sig)); + DataBuffer sig2; + EXPECT_TRUE(ImportPrivateKeyAndSignHashedData(k, data, &sig, &sig2)); }; // Importing a private key in PKCS#8 format must fail when the outer ASN.1 diff --git a/gtests/pk11_gtest/pk11_gtest.gyp b/gtests/pk11_gtest/pk11_gtest.gyp index 4171ea3828..44778f51b4 100644 --- a/gtests/pk11_gtest/pk11_gtest.gyp +++ b/gtests/pk11_gtest/pk11_gtest.gyp @@ -44,6 +44,7 @@ 'pk11_rsapkcs1_unittest.cc', 'pk11_rsapss_unittest.cc', 'pk11_seed_cbc_unittest.cc', + 'pk11_signature_test.cc', '<(DEPTH)/gtests/common/gtests.cc' ], 'dependencies': [ diff --git a/gtests/pk11_gtest/pk11_rsapkcs1_unittest.cc b/gtests/pk11_gtest/pk11_rsapkcs1_unittest.cc index db31f0dacb..7ae7189823 100644 --- a/gtests/pk11_gtest/pk11_rsapkcs1_unittest.cc +++ b/gtests/pk11_gtest/pk11_rsapkcs1_unittest.cc @@ -15,6 +15,7 @@ #include "pk11pub.h" #include "secerr.h" #include "sechash.h" +#include "pk11_signature_test.h" #include "testvectors/rsa_signature_2048_sha224-vectors.h" #include "testvectors/rsa_signature_2048_sha256-vectors.h" @@ -28,10 +29,46 @@ namespace nss_test { +CK_MECHANISM_TYPE RsaHashToComboMech(SECOidTag hash) { + switch (hash) { + case SEC_OID_SHA1: + return CKM_SHA1_RSA_PKCS; + case SEC_OID_SHA224: + return CKM_SHA224_RSA_PKCS; + case SEC_OID_SHA256: + return CKM_SHA256_RSA_PKCS; + case SEC_OID_SHA384: + return CKM_SHA384_RSA_PKCS; + case SEC_OID_SHA512: + return CKM_SHA512_RSA_PKCS; + default: + break; + } + return CKM_INVALID_MECHANISM; +} + +class Pkcs11RsaBaseTest : public Pk11SignatureTest { + protected: + Pkcs11RsaBaseTest(SECOidTag hashOid) + : Pk11SignatureTest(CKM_RSA_PKCS, hashOid, RsaHashToComboMech(hashOid)) {} + + void Verify(const RsaSignatureTestVector vec) { + Pkcs11SignatureTestParams params = { + DataBuffer(), DataBuffer(vec.public_key.data(), vec.public_key.size()), + DataBuffer(vec.msg.data(), vec.msg.size()), + DataBuffer(vec.sig.data(), vec.sig.size())}; + Pk11SignatureTest::Verify(params, (bool)vec.valid); + } +}; + class Pkcs11RsaPkcs1WycheproofTest - : public ::testing::TestWithParam { + : public Pkcs11RsaBaseTest, + public ::testing::WithParamInterface { + public: + Pkcs11RsaPkcs1WycheproofTest() : Pkcs11RsaBaseTest(GetParam().hash_oid) {} + protected: - void Derive(const RsaSignatureTestVector vec) { + void Verify1(const RsaSignatureTestVector vec) { SECItem spki_item = {siBuffer, toUcharPtr(vec.public_key.data()), static_cast(vec.public_key.size())}; @@ -210,7 +247,13 @@ TEST(RsaPkcs1Test, RequireNullParameter) { #endif } -TEST_P(Pkcs11RsaPkcs1WycheproofTest, Verify) { Derive(GetParam()); } +TEST_P(Pkcs11RsaPkcs1WycheproofTest, Verify) { + /* Using VFY_ interface */ + Verify1(GetParam()); + /* Using PKCS #11 interface */ + setSkipRaw(true); + Verify(GetParam()); +} INSTANTIATE_TEST_SUITE_P( Wycheproof2048RsaSignatureSha224Test, Pkcs11RsaPkcs1WycheproofTest, diff --git a/gtests/pk11_gtest/pk11_rsapss_unittest.cc b/gtests/pk11_gtest/pk11_rsapss_unittest.cc index 06c3ae32a6..e8428f794f 100644 --- a/gtests/pk11_gtest/pk11_rsapss_unittest.cc +++ b/gtests/pk11_gtest/pk11_rsapss_unittest.cc @@ -9,7 +9,6 @@ #include "pk11pub.h" #include "sechash.h" -#include "cpputil.h" #include "databuffer.h" #include "gtest/gtest.h" @@ -28,83 +27,68 @@ namespace nss_test { -class Pkcs11RsaPssTestWycheproof - : public ::testing::TestWithParam { - protected: - void TestPss(const RsaPssTestVector& vec) { - SECItem spki_item = {siBuffer, toUcharPtr(vec.public_key.data()), - static_cast(vec.public_key.size())}; - - ScopedCERTSubjectPublicKeyInfo cert_spki( - SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item)); - ASSERT_TRUE(cert_spki); - - ScopedSECKEYPublicKey pub_key(SECKEY_ExtractPublicKey(cert_spki.get())); - ASSERT_TRUE(pub_key); - - DataBuffer hash; - hash.Allocate(static_cast(HASH_ResultLenByOidTag(vec.hash_oid))); - SECStatus rv = PK11_HashBuf(vec.hash_oid, toUcharPtr(hash.data()), - toUcharPtr(vec.msg.data()), vec.msg.size()); - ASSERT_EQ(rv, SECSuccess); - - // Verify. - SECItem hash_item = {siBuffer, toUcharPtr(hash.data()), - static_cast(hash.len())}; - SECItem sig_item = {siBuffer, toUcharPtr(vec.sig.data()), - static_cast(vec.sig.size())}; - CK_MECHANISM_TYPE hash_mech = 0; - switch (vec.hash_oid) { - case SEC_OID_SHA1: - hash_mech = CKM_SHA_1; - break; - case SEC_OID_SHA224: - hash_mech = CKM_SHA224; - break; - case SEC_OID_SHA256: - hash_mech = CKM_SHA256; - break; - case SEC_OID_SHA384: - hash_mech = CKM_SHA384; - break; - case SEC_OID_SHA512: - hash_mech = CKM_SHA512; - break; - default: - ASSERT_TRUE(hash_mech); - return; - } - - CK_RSA_PKCS_PSS_PARAMS pss_params = {hash_mech, vec.mgf_hash, vec.sLen}; - SECItem params = {siBuffer, reinterpret_cast(&pss_params), - sizeof(pss_params)}; - - rv = PK11_VerifyWithMechanism(pub_key.get(), CKM_RSA_PKCS_PSS, ¶ms, - &sig_item, &hash_item, nullptr); - EXPECT_EQ(vec.valid ? SECSuccess : SECFailure, rv); - }; -}; +CK_MECHANISM_TYPE RsaPssMapCombo(SECOidTag hashOid) { + switch (hashOid) { + case SEC_OID_SHA1: + return CKM_SHA1_RSA_PKCS_PSS; + case SEC_OID_SHA224: + return CKM_SHA224_RSA_PKCS_PSS; + case SEC_OID_SHA256: + return CKM_SHA256_RSA_PKCS_PSS; + case SEC_OID_SHA384: + return CKM_SHA384_RSA_PKCS_PSS; + case SEC_OID_SHA512: + return CKM_SHA512_RSA_PKCS_PSS; + default: + break; + } + return CKM_INVALID_MECHANISM; +} -class Pkcs11RsaPssTest : public Pk11SignatureTest { - public: - Pkcs11RsaPssTest() : Pk11SignatureTest(CKM_RSA_PKCS_PSS, SEC_OID_SHA1) { - pss_params_.hashAlg = CKM_SHA_1; - pss_params_.mgf = CKG_MGF1_SHA1; - pss_params_.sLen = HASH_ResultLenByOidTag(SEC_OID_SHA1); +class Pkcs11RsaPssTestBase : public Pk11SignatureTest { + protected: + Pkcs11RsaPssTestBase(SECOidTag hashOid, CK_RSA_PKCS_MGF_TYPE mgf, int sLen) + : Pk11SignatureTest(CKM_RSA_PKCS_PSS, hashOid, RsaPssMapCombo(hashOid)) { + pss_params_.hashAlg = PK11_AlgtagToMechanism(hashOid); + pss_params_.mgf = mgf; + pss_params_.sLen = sLen; params_.type = siBuffer; params_.data = reinterpret_cast(&pss_params_); params_.len = sizeof(pss_params_); } - protected: const SECItem* parameters() const { return ¶ms_; } + void Verify(const RsaPssTestVector& vec) { + Pkcs11SignatureTestParams params = { + DataBuffer(), DataBuffer(vec.public_key.data(), vec.public_key.size()), + DataBuffer(vec.msg.data(), vec.msg.size()), + DataBuffer(vec.sig.data(), vec.sig.size())}; + + Pk11SignatureTest::Verify(params, vec.valid); + } + private: CK_RSA_PKCS_PSS_PARAMS pss_params_; SECItem params_; }; +class Pkcs11RsaPssTest : public Pkcs11RsaPssTestBase { + public: + Pkcs11RsaPssTest() + : Pkcs11RsaPssTestBase(SEC_OID_SHA1, CKG_MGF1_SHA1, SHA1_LENGTH) {} +}; + +class Pkcs11RsaPssTestWycheproof + : public Pkcs11RsaPssTestBase, + public ::testing::WithParamInterface { + public: + Pkcs11RsaPssTestWycheproof() + : Pkcs11RsaPssTestBase(GetParam().hash_oid, GetParam().mgf_hash, + GetParam().sLen) {} +}; + TEST_F(Pkcs11RsaPssTest, GenerateAndSignAndVerify) { // Sign data with a 1024-bit RSA key, using PSS/SHA-256. SECOidTag hashOid = SEC_OID_SHA256; @@ -179,7 +163,9 @@ class Pkcs11RsaPssVectorTest : public Pkcs11RsaPssTest, public ::testing::WithParamInterface {}; -TEST_P(Pkcs11RsaPssVectorTest, Verify) { Verify(GetParam()); } +TEST_P(Pkcs11RsaPssVectorTest, Verify) { + Pk11SignatureTest::Verify(GetParam()); +} TEST_P(Pkcs11RsaPssVectorTest, SignAndVerify) { SignAndVerify(GetParam()); } @@ -227,7 +213,7 @@ static const Pkcs11SignatureTestParams kRsaPssVectors[] = { INSTANTIATE_TEST_SUITE_P(RsaPssSignVerify, Pkcs11RsaPssVectorTest, ::testing::ValuesIn(kRsaPssVectors)); -TEST_P(Pkcs11RsaPssTestWycheproof, Verify) { TestPss(GetParam()); } +TEST_P(Pkcs11RsaPssTestWycheproof, Verify) { Verify(GetParam()); } INSTANTIATE_TEST_SUITE_P( Wycheproof2048RsaPssSha120Test, Pkcs11RsaPssTestWycheproof, diff --git a/gtests/pk11_gtest/pk11_signature_test.cc b/gtests/pk11_gtest/pk11_signature_test.cc new file mode 100644 index 0000000000..7ef51812c9 --- /dev/null +++ b/gtests/pk11_gtest/pk11_signature_test.cc @@ -0,0 +1,181 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include +#include "nss.h" +#include "pk11pub.h" +#include "sechash.h" +#include "prerror.h" + +#include "cpputil.h" +#include "nss_scoped_ptrs.h" +#include "databuffer.h" + +#include "gtest/gtest.h" +#include "pk11_signature_test.h" + +namespace nss_test { + +ScopedSECKEYPrivateKey Pk11SignatureTest::ImportPrivateKey( + const DataBuffer& pkcs8) { + ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); + if (!slot) { + ADD_FAILURE() << "No slot"; + return nullptr; + } + + SECItem pkcs8Item = {siBuffer, toUcharPtr(pkcs8.data()), + static_cast(pkcs8.len())}; + + SECKEYPrivateKey* key = nullptr; + SECStatus rv = PK11_ImportDERPrivateKeyInfoAndReturnKey( + slot.get(), &pkcs8Item, nullptr, nullptr, false, false, KU_ALL, &key, + nullptr); + + if (rv != SECSuccess) { + return nullptr; + } + + return ScopedSECKEYPrivateKey(key); +} + +ScopedSECKEYPublicKey Pk11SignatureTest::ImportPublicKey( + const DataBuffer& spki) { + SECItem spkiItem = {siBuffer, toUcharPtr(spki.data()), + static_cast(spki.len())}; + + ScopedCERTSubjectPublicKeyInfo certSpki( + SECKEY_DecodeDERSubjectPublicKeyInfo(&spkiItem)); + if (!certSpki) { + return nullptr; + } + + return ScopedSECKEYPublicKey(SECKEY_ExtractPublicKey(certSpki.get())); +} + +bool Pk11SignatureTest::SignHashedData(ScopedSECKEYPrivateKey& privKey, + const DataBuffer& hash, + DataBuffer* sig) { + SECItem hashItem = {siBuffer, toUcharPtr(hash.data()), + static_cast(hash.len())}; + unsigned int sigLen = PK11_SignatureLen(privKey.get()); + EXPECT_LT(0, (int)sigLen); + sig->Allocate(static_cast(sigLen)); + SECItem sigItem = {siBuffer, toUcharPtr(sig->data()), + static_cast(sig->len())}; + SECStatus rv = PK11_SignWithMechanism(privKey.get(), mechanism_, parameters(), + &sigItem, &hashItem); + EXPECT_EQ(sigLen, sigItem.len); + return rv == SECSuccess; +} + +bool Pk11SignatureTest::SignData(ScopedSECKEYPrivateKey& privKey, + const DataBuffer& data, DataBuffer* sig) { + unsigned int sigLen = PK11_SignatureLen(privKey.get()); + bool result = true; + EXPECT_LT(0, (int)sigLen); + sig->Allocate(static_cast(sigLen)); + + // test the hash and verify interface */ + PK11Context* context = PK11_CreateContextByPrivKey( + combo_, CKA_SIGN, privKey.get(), parameters()); + if (context == NULL) { + ADD_FAILURE() << "Failed to sign data: couldn't create context" + << "\n" + << "mech=0x" << std::hex << combo_ << "\n" + << "Error: " << PORT_ErrorToString(PORT_GetError()); + return false; + } + SECStatus rv = PK11_DigestOp(context, data.data(), data.len()); + if (rv != SECSuccess) { + ADD_FAILURE() << "Failed to sign data: Update failed\n" + << "Error: " << PORT_ErrorToString(PORT_GetError()); + PK11_DestroyContext(context, PR_TRUE); + return false; + } + unsigned int len = sigLen; + rv = PK11_DigestFinal(context, sig->data(), &len, sigLen); + if (rv != SECSuccess) { + ADD_FAILURE() << "Failed to sign data: final failed\n" + << "Error: " << PORT_ErrorToString(PORT_GetError()); + result = false; + } + if (len != sigLen) { + ADD_FAILURE() << "sign data: unexpected len " << len << "expected" + << sigLen; + result = false; + } + PK11_DestroyContext(context, PR_TRUE); + return result; +} + +bool Pk11SignatureTest::ImportPrivateKeyAndSignHashedData( + const DataBuffer& pkcs8, const DataBuffer& data, DataBuffer* sig, + DataBuffer* sig2) { + ScopedSECKEYPrivateKey privKey(ImportPrivateKey(pkcs8)); + if (!privKey) { + return false; + } + + DataBuffer hash; + if (!ComputeHash(data, &hash)) { + ADD_FAILURE() << "Failed to compute hash"; + return false; + } + if (!SignHashedData(privKey, hash, sig)) { + ADD_FAILURE() << "Failed to sign hashed data"; + return false; + } + if (!SignData(privKey, data, sig2)) { + /* failure was already added by SignData, with an error message */ + return false; + } + return true; +} + +void Pk11SignatureTest::Verify(const Pkcs11SignatureTestParams& params, + const DataBuffer& sig, bool valid) { + ScopedSECKEYPublicKey pubKey(ImportPublicKey(params.spki_)); + ASSERT_TRUE(pubKey); + + SECStatus rv; + DataBuffer hash; + + SECItem sigItem = {siBuffer, toUcharPtr(sig.data()), + static_cast(sig.len())}; + + /* RSA single shot requires encoding the hash before calling + * VerifyWithMechanism. We already check that mechanism + * with the VFY_ interface, so just do the combined hash/Verify + * in that case */ + if (!skip_raw_) { + ASSERT_TRUE(ComputeHash(params.data_, &hash)); + + // Verify. + SECItem hashItem = {siBuffer, toUcharPtr(hash.data()), + static_cast(hash.len())}; + rv = PK11_VerifyWithMechanism(pubKey.get(), mechanism_, parameters(), + &sigItem, &hashItem, nullptr); + EXPECT_EQ(rv, valid ? SECSuccess : SECFailure); + } + + // test the hash and verify interface */ + PK11Context* context = PK11_CreateContextByPubKey( + combo_, CKA_VERIFY, pubKey.get(), parameters(), NULL); + /* we assert here because we'll crash if we try to continue + * without a context. */ + ASSERT_NE((void*)context, (void*)NULL) + << "CreateContext failed Error:" << PORT_ErrorToString(PORT_GetError()) + << "\n"; + rv = PK11_DigestOp(context, params.data_.data(), params.data_.len()); + /* expect success unconditionally here */ + EXPECT_EQ(rv, SECSuccess); + unsigned int len; + rv = PK11_DigestFinal(context, sigItem.data, &len, sigItem.len); + EXPECT_EQ(rv, valid ? SECSuccess : SECFailure) + << "verify failed Error:" << PORT_ErrorToString(PORT_GetError()) << "\n"; + PK11_DestroyContext(context, PR_TRUE); +} + +} // namespace nss_test diff --git a/gtests/pk11_gtest/pk11_signature_test.h b/gtests/pk11_gtest/pk11_signature_test.h index cd46f17d74..82ef038963 100644 --- a/gtests/pk11_gtest/pk11_signature_test.h +++ b/gtests/pk11_gtest/pk11_signature_test.h @@ -7,7 +7,6 @@ #include "pk11pub.h" #include "sechash.h" -#include "cpputil.h" #include "nss_scoped_ptrs.h" #include "databuffer.h" @@ -25,46 +24,18 @@ struct Pkcs11SignatureTestParams { class Pk11SignatureTest : public ::testing::Test { protected: - Pk11SignatureTest(CK_MECHANISM_TYPE mech, SECOidTag hash_oid) - : mechanism_(mech), hash_oid_(hash_oid) {} + Pk11SignatureTest(CK_MECHANISM_TYPE mech, SECOidTag hash_oid, + CK_MECHANISM_TYPE combo) + : mechanism_(mech), hash_oid_(hash_oid), combo_(combo) { + skip_raw_ = false; + } virtual const SECItem* parameters() const { return nullptr; } CK_MECHANISM_TYPE mechanism() const { return mechanism_; } + void setSkipRaw(bool skip_raw) { skip_raw_ = true; } - ScopedSECKEYPrivateKey ImportPrivateKey(const DataBuffer& pkcs8) { - ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); - if (!slot) { - ADD_FAILURE() << "No slot"; - return nullptr; - } - - SECItem pkcs8Item = {siBuffer, toUcharPtr(pkcs8.data()), - static_cast(pkcs8.len())}; - - SECKEYPrivateKey* key = nullptr; - SECStatus rv = PK11_ImportDERPrivateKeyInfoAndReturnKey( - slot.get(), &pkcs8Item, nullptr, nullptr, false, false, KU_ALL, &key, - nullptr); - - if (rv != SECSuccess) { - return nullptr; - } - - return ScopedSECKEYPrivateKey(key); - } - - ScopedSECKEYPublicKey ImportPublicKey(const DataBuffer& spki) { - SECItem spkiItem = {siBuffer, toUcharPtr(spki.data()), - static_cast(spki.len())}; - - ScopedCERTSubjectPublicKeyInfo certSpki( - SECKEY_DecodeDERSubjectPublicKeyInfo(&spkiItem)); - if (!certSpki) { - return nullptr; - } - - return ScopedSECKEYPublicKey(SECKEY_ExtractPublicKey(certSpki.get())); - } + ScopedSECKEYPrivateKey ImportPrivateKey(const DataBuffer& pkcs8); + ScopedSECKEYPublicKey ImportPublicKey(const DataBuffer& spki); bool ComputeHash(const DataBuffer& data, DataBuffer* hash) { hash->Allocate(static_cast(HASH_ResultLenByOidTag(hash_oid_))); @@ -74,66 +45,37 @@ class Pk11SignatureTest : public ::testing::Test { } bool SignHashedData(ScopedSECKEYPrivateKey& privKey, const DataBuffer& hash, - DataBuffer* sig) { - SECItem hashItem = {siBuffer, toUcharPtr(hash.data()), - static_cast(hash.len())}; - int sigLen = PK11_SignatureLen(privKey.get()); - EXPECT_LT(0, sigLen); - sig->Allocate(static_cast(sigLen)); - SECItem sigItem = {siBuffer, toUcharPtr(sig->data()), - static_cast(sig->len())}; - SECStatus rv = PK11_SignWithMechanism(privKey.get(), mechanism_, - parameters(), &sigItem, &hashItem); - return rv == SECSuccess; - } - + DataBuffer* sig); + bool SignData(ScopedSECKEYPrivateKey& privKey, const DataBuffer& data, + DataBuffer* sig); bool ImportPrivateKeyAndSignHashedData(const DataBuffer& pkcs8, const DataBuffer& data, - DataBuffer* sig) { - ScopedSECKEYPrivateKey privKey(ImportPrivateKey(pkcs8)); - if (!privKey) { - return false; - } - - DataBuffer hash; - if (!ComputeHash(data, &hash)) { - ADD_FAILURE() << "Failed to compute hash"; - return false; - } - return SignHashedData(privKey, hash, sig); - } - - void Verify(const Pkcs11SignatureTestParams& params, const DataBuffer& sig) { - ScopedSECKEYPublicKey pubKey(ImportPublicKey(params.spki_)); - ASSERT_TRUE(pubKey); - - DataBuffer hash; - ASSERT_TRUE(ComputeHash(params.data_, &hash)); + DataBuffer* sig, DataBuffer* sig2); + void Verify(const Pkcs11SignatureTestParams& params, const DataBuffer& sig, + bool valid); - // Verify. - SECItem hashItem = {siBuffer, toUcharPtr(hash.data()), - static_cast(hash.len())}; - SECItem sigItem = {siBuffer, toUcharPtr(sig.data()), - static_cast(sig.len())}; - SECStatus rv = PK11_VerifyWithMechanism( - pubKey.get(), mechanism_, parameters(), &sigItem, &hashItem, nullptr); - EXPECT_EQ(rv, SECSuccess); + void Verify(const Pkcs11SignatureTestParams& params, bool valid) { + Verify(params, params.signature_, valid); } void Verify(const Pkcs11SignatureTestParams& params) { - Verify(params, params.signature_); + Verify(params, params.signature_, true); } void SignAndVerify(const Pkcs11SignatureTestParams& params) { DataBuffer sig; - ASSERT_TRUE( - ImportPrivateKeyAndSignHashedData(params.pkcs8_, params.data_, &sig)); - Verify(params, sig); + DataBuffer sig2; + ASSERT_TRUE(ImportPrivateKeyAndSignHashedData(params.pkcs8_, params.data_, + &sig, &sig2)); + Verify(params, sig, true); + Verify(params, sig2, true); } private: CK_MECHANISM_TYPE mechanism_; SECOidTag hash_oid_; + CK_MECHANISM_TYPE combo_; + bool skip_raw_; }; } // namespace nss_test diff --git a/lib/nss/nss.def b/lib/nss/nss.def index db912e1ec9..91486ceff0 100644 --- a/lib/nss/nss.def +++ b/lib/nss/nss.def @@ -1219,4 +1219,11 @@ PK11_HPKE_ExportContext; PK11_HPKE_ImportContext; ;+ local: ;+ *; -;+}; \ No newline at end of file +;+}; +;+NSS_3.64 { # NSS 3.64 release +;+ global: +PK11_CreateContextByPubKey; +PK11_CreateContextByPrivKey; +;+ local: +;+ *; +;+}; diff --git a/lib/pk11wrap/pk11cxt.c b/lib/pk11wrap/pk11cxt.c index b1569ebf94..9deff08d5e 100644 --- a/lib/pk11wrap/pk11cxt.c +++ b/lib/pk11wrap/pk11cxt.c @@ -125,7 +125,7 @@ SECStatus pk11_restoreContext(PK11Context *context, void *space, unsigned long savedLength) { CK_RV crv; - CK_OBJECT_HANDLE objectID = (context->key) ? context->key->objectID : CK_INVALID_HANDLE; + CK_OBJECT_HANDLE objectID = context->objectID; PORT_Assert(space != NULL); if (space == NULL) { @@ -150,7 +150,7 @@ SECStatus pk11_Finalize(PK11Context *context); */ static CK_RV pk11_contextInitMessage(PK11Context *context, CK_MECHANISM_PTR mech, - PK11SymKey *key, CK_C_MessageEncryptInit initFunc, + CK_C_MessageEncryptInit initFunc, CK_FLAGS flags, CK_RV scrv) { PK11SlotInfo *slot = context->slot; @@ -197,7 +197,6 @@ static SECStatus pk11_context_init(PK11Context *context, CK_MECHANISM *mech_info) { CK_RV crv; - PK11SymKey *symKey = context->key; SECStatus rv = SECSuccess; context->simulate_message = PR_FALSE; @@ -212,7 +211,7 @@ pk11_context_init(PK11Context *context, CK_MECHANISM *mech_info) if (context->fortezzaHack) { CK_ULONG count = 0; /* generate the IV for fortezza */ - crv = PK11_GETTAB(context->slot)->C_EncryptInit(context->session, mech_info, symKey->objectID); + crv = PK11_GETTAB(context->slot)->C_EncryptInit(context->session, mech_info, context->objectID); if (crv != CKR_OK) { PK11_ExitContextMonitor(context); break; @@ -221,7 +220,7 @@ pk11_context_init(PK11Context *context, CK_MECHANISM *mech_info) ->C_EncryptFinal(context->session, NULL, &count); } - crv = PK11_GETTAB(context->slot)->C_DecryptInit(context->session, mech_info, symKey->objectID); + crv = PK11_GETTAB(context->slot)->C_DecryptInit(context->session, mech_info, context->objectID); PK11_ExitContextMonitor(context); break; case CKA_SIGN: @@ -230,8 +229,15 @@ pk11_context_init(PK11Context *context, CK_MECHANISM *mech_info) PK11_ExitContextMonitor(context); break; case CKA_VERIFY: + /* NOTE: we previously has this set to C_SignInit for Macing. + * It turns out now one could possibly use it that way, though, + * because PK11_HashOp() always called C_VerifyUpdate on CKA_VERIFY, + * which would have failed. So everyone just calls us with CKA_SIGN + * when Macing even when they are verifying, no need to 'do it + * for them'. It needs to be VerifyInit now so that we can do + * PKCS #11 hash/Verify combo operations. */ PK11_EnterContextMonitor(context); - crv = PK11_GETTAB(context->slot)->C_SignInit(context->session, mech_info, symKey->objectID); + crv = PK11_GETTAB(context->slot)->C_VerifyInit(context->session, mech_info, context->objectID); PK11_ExitContextMonitor(context); break; case CKA_DIGEST: @@ -241,22 +247,22 @@ pk11_context_init(PK11Context *context, CK_MECHANISM *mech_info) break; case CKA_NSS_MESSAGE | CKA_ENCRYPT: - crv = pk11_contextInitMessage(context, mech_info, symKey, + crv = pk11_contextInitMessage(context, mech_info, PK11_GETTAB(context->slot)->C_MessageEncryptInit, CKF_MESSAGE_ENCRYPT, CKR_OK); break; case CKA_NSS_MESSAGE | CKA_DECRYPT: - crv = pk11_contextInitMessage(context, mech_info, symKey, + crv = pk11_contextInitMessage(context, mech_info, PK11_GETTAB(context->slot)->C_MessageDecryptInit, CKF_MESSAGE_DECRYPT, CKR_OK); break; case CKA_NSS_MESSAGE | CKA_SIGN: - crv = pk11_contextInitMessage(context, mech_info, symKey, + crv = pk11_contextInitMessage(context, mech_info, PK11_GETTAB(context->slot)->C_MessageSignInit, CKF_MESSAGE_SIGN, CKR_FUNCTION_NOT_SUPPORTED); break; case CKA_NSS_MESSAGE | CKA_VERIFY: - crv = pk11_contextInitMessage(context, mech_info, symKey, + crv = pk11_contextInitMessage(context, mech_info, PK11_GETTAB(context->slot)->C_MessageVerifyInit, CKF_MESSAGE_VERIFY, CKR_FUNCTION_NOT_SUPPORTED); break; @@ -348,16 +354,17 @@ _PK11_ContextGetAEADSimulation(PK11Context *context) */ static PK11Context * pk11_CreateNewContextInSlot(CK_MECHANISM_TYPE type, - PK11SlotInfo *slot, CK_ATTRIBUTE_TYPE operation, PK11SymKey *symKey, - SECItem *param) + PK11SlotInfo *slot, CK_ATTRIBUTE_TYPE operation, + PK11SymKey *symKey, CK_OBJECT_HANDLE objectID, + const SECItem *param, void *pwArg) { CK_MECHANISM mech_info; PK11Context *context; SECStatus rv; PORT_Assert(slot != NULL); - if (!slot || (!symKey && ((operation != CKA_DIGEST) || - (type == CKM_SKIPJACK_CBC64)))) { + if (!slot || ((objectID == CK_INVALID_HANDLE) && ((operation != CKA_DIGEST) || + (type == CKM_SKIPJACK_CBC64)))) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return NULL; } @@ -382,10 +389,16 @@ pk11_CreateNewContextInSlot(CK_MECHANISM_TYPE type, /* initialize the critical fields of the context */ context->operation = operation; + /* If we were given a symKey, keep our own reference to it so + * that the key doesn't disappear in the middle of the operation + * if the caller frees it. Public and Private keys are not reference + * counted, so the caller just has to keep his copies around until + * the operation completes */ context->key = symKey ? PK11_ReferenceSymKey(symKey) : NULL; + context->objectID = objectID; context->slot = PK11_ReferenceSlot(slot); context->session = pk11_GetNewSession(slot, &context->ownSession); - context->cx = symKey ? symKey->cx : NULL; + context->pwArg = pwArg; /* get our session */ context->savedData = NULL; @@ -474,11 +487,11 @@ PK11_CreateContextByRawKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, /* * Create a context from a key. We really should make sure we aren't using - * the same key in multiple session! + * the same key in multiple sessions! */ PK11Context * PK11_CreateContextBySymKey(CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE operation, - PK11SymKey *symKey, SECItem *param) + PK11SymKey *symKey, const SECItem *param) { PK11SymKey *newKey; PK11Context *context; @@ -491,13 +504,72 @@ PK11_CreateContextBySymKey(CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE operation, symKey = newKey; } - /* Context Adopts the symKey.... */ + /* Context keeps its reference to the symKey, so it's safe to + * free our reference we we are through, even though we may have + * created the key using pk11_ForceSlot. */ context = pk11_CreateNewContextInSlot(type, symKey->slot, operation, symKey, - param); + symKey->objectID, param, symKey->cx); PK11_FreeSymKey(symKey); return context; } +/* To support multipart public key operations (like hash/verify operations), + * we need to create contexts with public keys. */ +PK11Context * +PK11_CreateContextByPubKey(CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE operation, + SECKEYPublicKey *pubKey, const SECItem *param, + void *pwArg) +{ + PK11SlotInfo *slot = pubKey->pkcs11Slot; + SECItem nullparam = { 0, 0, 0 }; + + /* if this slot doesn't support the mechanism, go to a slot that does */ + /* public keys have all their data in the public key data structure, + * so there's no need to export the old key, just import this one. The + * import manages consistancy of the public key data structure */ + if (slot == NULL || !PK11_DoesMechanism(slot, type)) { + CK_OBJECT_HANDLE objectID; + slot = PK11_GetBestSlot(type, NULL); + if (slot == NULL) { + return NULL; + } + objectID = PK11_ImportPublicKey(slot, pubKey, PR_FALSE); + PK11_FreeSlot(slot); + if (objectID == CK_INVALID_HANDLE) { + return NULL; + } + } + + /* unlike symkeys, we accept a NULL parameter. map a null parameter + * to the empty parameter. This matches the semantics of + * PK11_VerifyWithMechanism */ + return pk11_CreateNewContextInSlot(type, pubKey->pkcs11Slot, operation, + NULL, pubKey->pkcs11ID, + param ? param : &nullparam, pwArg); +} + +/* To support multipart private key operations (like hash/sign operations), + * we need to create contexts with private keys. */ +PK11Context * +PK11_CreateContextByPrivKey(CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE operation, + SECKEYPrivateKey *privKey, const SECItem *param) +{ + SECItem nullparam = { 0, 0, 0 }; + /* Private keys are generally not movable. If the token the + * private key lives on can't do the operation, generally we are + * stuck anyway. So no need to try to manipulate the key into + * another token */ + + /* if this slot doesn't support the mechanism, go to a slot that does */ + /* unlike symkeys, we accept a NULL parameter. map a null parameter + * to the empty parameter. This matches the semantics of + * PK11_SignWithMechanism */ + return pk11_CreateNewContextInSlot(type, privKey->pkcs11Slot, operation, + NULL, privKey->pkcs11ID, + param ? param : &nullparam, + privKey->wincx); +} + /* * Digest contexts don't need keys, but the do need to find a slot. * Macing should use PK11_CreateContextBySymKey. @@ -523,7 +595,8 @@ PK11_CreateDigestContext(SECOidTag hashAlg) param.len = 0; param.type = 0; - context = pk11_CreateNewContextInSlot(type, slot, CKA_DIGEST, NULL, ¶m); + context = pk11_CreateNewContextInSlot(type, slot, CKA_DIGEST, NULL, + CK_INVALID_HANDLE, ¶m, NULL); PK11_FreeSlot(slot); return context; } @@ -541,7 +614,8 @@ PK11_CloneContext(PK11Context *old) unsigned long len; newcx = pk11_CreateNewContextInSlot(old->type, old->slot, old->operation, - old->key, old->param); + old->key, old->objectID, old->param, + old->pwArg); if (newcx == NULL) return NULL; diff --git a/lib/pk11wrap/pk11pub.h b/lib/pk11wrap/pk11pub.h index 1a074219b0..559fc3c661 100644 --- a/lib/pk11wrap/pk11pub.h +++ b/lib/pk11wrap/pk11pub.h @@ -811,7 +811,17 @@ SECStatus PK11_VerifyWithMechanism(SECKEYPublicKey *key, **********************************************************************/ void PK11_DestroyContext(PK11Context *context, PRBool freeit); PK11Context *PK11_CreateContextBySymKey(CK_MECHANISM_TYPE type, - CK_ATTRIBUTE_TYPE operation, PK11SymKey *symKey, SECItem *param); + CK_ATTRIBUTE_TYPE operation, + PK11SymKey *symKey, + const SECItem *param); +PK11Context *PK11_CreateContextByPubKey(CK_MECHANISM_TYPE type, + CK_ATTRIBUTE_TYPE operation, + SECKEYPublicKey *pubKey, + const SECItem *param, void *pwArg); +PK11Context *PK11_CreateContextByPrivKey(CK_MECHANISM_TYPE type, + CK_ATTRIBUTE_TYPE operation, + SECKEYPrivateKey *privKey, + const SECItem *param); PK11Context *PK11_CreateDigestContext(SECOidTag hashAlg); PK11Context *PK11_CloneContext(PK11Context *old); SECStatus PK11_DigestBegin(PK11Context *cx); @@ -1007,7 +1017,7 @@ PRBool SECMOD_HasRootCerts(void); /********************************************************************** * Other Utilities **********************************************************************/ -/* +/* * Get the state of the system FIPS mode - * NSS uses this to force FIPS mode if the system bit is on. This returns * the system state independent of the database state and can be called diff --git a/lib/pk11wrap/secmodti.h b/lib/pk11wrap/secmodti.h index 52c839119c..04c63a8690 100644 --- a/lib/pk11wrap/secmodti.h +++ b/lib/pk11wrap/secmodti.h @@ -149,12 +149,13 @@ struct PK11ContextStr { * doing (CKA_ENCRYPT, CKA_SIGN, * CKA_HASH, etc.) */ PK11SymKey *key; /* symetric key for this context */ + CK_OBJECT_HANDLE objectID; /* object handle to key */ PK11SlotInfo *slot; /* slot this context is using */ CK_SESSION_HANDLE session; /* session this context is using */ PZLock *sessionLock; /* lock before accessing a PKCS #11 * session */ PRBool ownSession; /* do we own the session? */ - void *cx; /* window context for login */ + void *pwArg; /* applicaton specific passwd arg */ void *savedData; /* save data when we are * multiplexing on a single context */ unsigned long savedLength; /* length of the saved context */ diff --git a/lib/softoken/pkcs11.c b/lib/softoken/pkcs11.c index 216c5ac184..33dacc6daf 100644 --- a/lib/softoken/pkcs11.c +++ b/lib/softoken/pkcs11.c @@ -318,6 +318,11 @@ static const struct mechanismList mechanisms[] = { { CKM_SHA256_RSA_PKCS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE }, { CKM_SHA384_RSA_PKCS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE }, { CKM_SHA512_RSA_PKCS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE }, + { CKM_SHA1_RSA_PKCS_PSS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE }, + { CKM_SHA224_RSA_PKCS_PSS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE }, + { CKM_SHA256_RSA_PKCS_PSS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE }, + { CKM_SHA384_RSA_PKCS_PSS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE }, + { CKM_SHA512_RSA_PKCS_PSS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE }, /* ------------------------- DSA Operations --------------------------- */ { CKM_DSA_KEY_PAIR_GEN, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_GENERATE_KEY_PAIR }, PR_TRUE }, { CKM_DSA, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_SN_VR }, PR_TRUE }, diff --git a/lib/softoken/pkcs11c.c b/lib/softoken/pkcs11c.c index b54d28de9e..9709f43394 100644 --- a/lib/softoken/pkcs11c.c +++ b/lib/softoken/pkcs11c.c @@ -57,6 +57,12 @@ #include "pkcs11f.h" +/* create a definition of SHA1 that's consistent + * with the rest of the CKM_SHAxxx hashes*/ +#define CKM_SHA1 CKM_SHA_1 +#define CKM_SHA1_HMAC CKM_SHA_1_HMAC +#define CKM_SHA1_HMAC_GENERAL CKM_SHA_1_HMAC_GENERAL + typedef struct { PRUint8 client_version[2]; PRUint8 random[46]; @@ -1858,12 +1864,12 @@ NSC_DigestInit(CK_SESSION_HANDLE hSession, return crv; } -#define INIT_MECH(mech, mmm) \ - case mech: { \ +#define INIT_MECH(mmm) \ + case CKM_##mmm: { \ mmm##Context *mmm##_ctx = mmm##_NewContext(); \ context->cipherInfo = (void *)mmm##_ctx; \ context->cipherInfoLen = mmm##_FlattenSize(mmm##_ctx); \ - context->currentMech = mech; \ + context->currentMech = CKM_##mmm; \ context->hashUpdate = (SFTKHash)mmm##_Update; \ context->end = (SFTKEnd)mmm##_End; \ context->destroy = (SFTKDestroy)mmm##_DestroyContext; \ @@ -1876,13 +1882,13 @@ NSC_DigestInit(CK_SESSION_HANDLE hSession, } switch (pMechanism->mechanism) { - INIT_MECH(CKM_MD2, MD2) - INIT_MECH(CKM_MD5, MD5) - INIT_MECH(CKM_SHA_1, SHA1) - INIT_MECH(CKM_SHA224, SHA224) - INIT_MECH(CKM_SHA256, SHA256) - INIT_MECH(CKM_SHA384, SHA384) - INIT_MECH(CKM_SHA512, SHA512) + INIT_MECH(MD2) + INIT_MECH(MD5) + INIT_MECH(SHA1) + INIT_MECH(SHA224) + INIT_MECH(SHA256) + INIT_MECH(SHA384) + INIT_MECH(SHA512) default: crv = CKR_MECHANISM_INVALID; @@ -2775,7 +2781,29 @@ NSC_SignInit(CK_SESSION_HANDLE hSession, } context->maxLen = nsslowkey_PrivateModulusLen(privKey); break; + +#define INIT_RSA_PSS_SIG_MECH(mmm) \ + case CKM_##mmm##_RSA_PKCS_PSS: \ + context->multi = PR_TRUE; \ + crv = sftk_doSub##mmm(context); \ + if (crv != CKR_OK) \ + break; \ + if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS)) { \ + crv = CKR_MECHANISM_PARAM_INVALID; \ + break; \ + } \ + if (((const CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter)->hashAlg != CKM_##mmm) { \ + crv = CKR_MECHANISM_PARAM_INVALID; \ + break; \ + } \ + goto finish_rsa_pss; + INIT_RSA_PSS_SIG_MECH(SHA1) + INIT_RSA_PSS_SIG_MECH(SHA224) + INIT_RSA_PSS_SIG_MECH(SHA256) + INIT_RSA_PSS_SIG_MECH(SHA384) + INIT_RSA_PSS_SIG_MECH(SHA512) case CKM_RSA_PKCS_PSS: + finish_rsa_pss: if (key_type != CKK_RSA) { crv = CKR_KEY_TYPE_INCONSISTENT; break; @@ -2803,18 +2831,18 @@ NSC_SignInit(CK_SESSION_HANDLE hSession, context->maxLen = nsslowkey_PrivateModulusLen(info->key); break; -#define INIT_DSA_SIGN_MECH(mmm) \ +#define INIT_DSA_SIG_MECH(mmm) \ case CKM_DSA_##mmm: \ context->multi = PR_TRUE; \ crv = sftk_doSub##mmm(context); \ if (crv != CKR_OK) \ break; \ goto finish_dsa; - INIT_DSA_SIGN_MECH(SHA1) - INIT_DSA_SIGN_MECH(SHA224) - INIT_DSA_SIGN_MECH(SHA256) - INIT_DSA_SIGN_MECH(SHA384) - INIT_DSA_SIGN_MECH(SHA512) + INIT_DSA_SIG_MECH(SHA1) + INIT_DSA_SIG_MECH(SHA224) + INIT_DSA_SIG_MECH(SHA256) + INIT_DSA_SIG_MECH(SHA384) + INIT_DSA_SIG_MECH(SHA512) case CKM_DSA: finish_dsa: if (key_type != CKK_DSA) { @@ -2832,18 +2860,18 @@ NSC_SignInit(CK_SESSION_HANDLE hSession, break; -#define INIT_ECDSA_SIGN_MECH(mmm) \ +#define INIT_ECDSA_SIG_MECH(mmm) \ case CKM_ECDSA_##mmm: \ context->multi = PR_TRUE; \ crv = sftk_doSub##mmm(context); \ if (crv != CKR_OK) \ break; \ goto finish_ecdsa; - INIT_ECDSA_SIGN_MECH(SHA1) - INIT_ECDSA_SIGN_MECH(SHA224) - INIT_ECDSA_SIGN_MECH(SHA256) - INIT_ECDSA_SIGN_MECH(SHA384) - INIT_ECDSA_SIGN_MECH(SHA512) + INIT_ECDSA_SIG_MECH(SHA1) + INIT_ECDSA_SIG_MECH(SHA224) + INIT_ECDSA_SIG_MECH(SHA256) + INIT_ECDSA_SIG_MECH(SHA384) + INIT_ECDSA_SIG_MECH(SHA512) case CKM_ECDSA: finish_ecdsa: if (key_type != CKK_EC) { @@ -2879,23 +2907,12 @@ NSC_SignInit(CK_SESSION_HANDLE hSession, INIT_HMAC_MECH(MD2) INIT_HMAC_MECH(MD5) + INIT_HMAC_MECH(SHA1) INIT_HMAC_MECH(SHA224) INIT_HMAC_MECH(SHA256) INIT_HMAC_MECH(SHA384) INIT_HMAC_MECH(SHA512) - case CKM_SHA_1_HMAC_GENERAL: - PORT_Assert(pMechanism->pParameter); - if (!pMechanism->pParameter || pMechanism->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)) { - crv = CKR_MECHANISM_PARAM_INVALID; - break; - } - crv = sftk_doMACInit(pMechanism->mechanism, context, key, - *(CK_ULONG *)pMechanism->pParameter); - break; - case CKM_SHA_1_HMAC: - crv = sftk_doMACInit(pMechanism->mechanism, context, key, SHA1_LENGTH); - break; case CKM_AES_CMAC_GENERAL: PORT_Assert(pMechanism->pParameter); if (!pMechanism->pParameter || pMechanism->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)) { @@ -3557,7 +3574,14 @@ NSC_VerifyInit(CK_SESSION_HANDLE hSession, context->destroy = sftk_Null; } break; + + INIT_RSA_PSS_SIG_MECH(SHA1) + INIT_RSA_PSS_SIG_MECH(SHA224) + INIT_RSA_PSS_SIG_MECH(SHA256) + INIT_RSA_PSS_SIG_MECH(SHA384) + INIT_RSA_PSS_SIG_MECH(SHA512) case CKM_RSA_PKCS_PSS: + finish_rsa_pss: if (key_type != CKK_RSA) { crv = CKR_KEY_TYPE_INCONSISTENT; break; @@ -3583,13 +3607,14 @@ NSC_VerifyInit(CK_SESSION_HANDLE hSession, context->destroy = (SFTKDestroy)sftk_Space; context->verify = (SFTKVerify)sftk_RSACheckSignPSS; break; - case CKM_DSA_SHA1: - context->multi = PR_TRUE; - crv = sftk_doSubSHA1(context); - if (crv != CKR_OK) - break; - /* fall through */ + + INIT_DSA_SIG_MECH(SHA1) + INIT_DSA_SIG_MECH(SHA224) + INIT_DSA_SIG_MECH(SHA256) + INIT_DSA_SIG_MECH(SHA384) + INIT_DSA_SIG_MECH(SHA512) case CKM_DSA: + finish_dsa: if (key_type != CKK_DSA) { crv = CKR_KEY_TYPE_INCONSISTENT; break; @@ -3602,13 +3627,14 @@ NSC_VerifyInit(CK_SESSION_HANDLE hSession, context->verify = (SFTKVerify)nsc_DSA_Verify_Stub; context->destroy = sftk_Null; break; - case CKM_ECDSA_SHA1: - context->multi = PR_TRUE; - crv = sftk_doSubSHA1(context); - if (crv != CKR_OK) - break; - /* fall through */ + + INIT_ECDSA_SIG_MECH(SHA1) + INIT_ECDSA_SIG_MECH(SHA224) + INIT_ECDSA_SIG_MECH(SHA256) + INIT_ECDSA_SIG_MECH(SHA384) + INIT_ECDSA_SIG_MECH(SHA512) case CKM_ECDSA: + finish_ecdsa: if (key_type != CKK_EC) { crv = CKR_KEY_TYPE_INCONSISTENT; break; @@ -3625,24 +3651,12 @@ NSC_VerifyInit(CK_SESSION_HANDLE hSession, INIT_HMAC_MECH(MD2) INIT_HMAC_MECH(MD5) + INIT_HMAC_MECH(SHA1) INIT_HMAC_MECH(SHA224) INIT_HMAC_MECH(SHA256) INIT_HMAC_MECH(SHA384) INIT_HMAC_MECH(SHA512) - case CKM_SHA_1_HMAC_GENERAL: - PORT_Assert(pMechanism->pParameter); - if (!pMechanism->pParameter) { - crv = CKR_MECHANISM_PARAM_INVALID; - break; - } - crv = sftk_doMACInit(pMechanism->mechanism, context, key, - *(CK_ULONG *)pMechanism->pParameter); - break; - case CKM_SHA_1_HMAC: - crv = sftk_doMACInit(pMechanism->mechanism, context, key, SHA1_LENGTH); - break; - case CKM_SSL3_MD5_MAC: PORT_Assert(pMechanism->pParameter); if (!pMechanism->pParameter) {