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 "prerror.h"
10 #include "pk11pub.h"
11 #include "sechash.h"
12 #include "cryptohi.h"
13 
14 #include "cpputil.h"
15 #include "databuffer.h"
16 #include "pk11_signature_test.h"
17 
18 #include "gtest/gtest.h"
19 #include "nss_scoped_ptrs.h"
20 
21 #include "testvectors/dsa-vectors.h"
22 
23 namespace nss_test {
24 CK_MECHANISM_TYPE
DsaHashToComboMech(SECOidTag hash)25 DsaHashToComboMech(SECOidTag hash) {
26   switch (hash) {
27     case SEC_OID_SHA1:
28       return CKM_DSA_SHA1;
29     case SEC_OID_SHA224:
30       return CKM_DSA_SHA224;
31     case SEC_OID_SHA256:
32       return CKM_DSA_SHA256;
33     case SEC_OID_SHA384:
34       return CKM_DSA_SHA384;
35     case SEC_OID_SHA512:
36       return CKM_DSA_SHA512;
37     default:
38       break;
39   }
40   return CKM_INVALID_MECHANISM;
41 }
42 
43 class Pkcs11DsaTestBase : public Pk11SignatureTest {
44  protected:
Pkcs11DsaTestBase(SECOidTag hashOid)45   Pkcs11DsaTestBase(SECOidTag hashOid)
46       : Pk11SignatureTest(CKM_DSA, hashOid, DsaHashToComboMech(hashOid)) {}
47 
Verify(const DsaTestVector vec)48   void Verify(const DsaTestVector vec) {
49     /* DSA vectors encode the signature in DER, we need to unwrap it before
50      * we can send the raw signatures to PKCS #11. */
51     DataBuffer pubKeyBuffer(vec.public_key.data(), vec.public_key.size());
52     ScopedSECKEYPublicKey nssPubKey(ImportPublicKey(pubKeyBuffer));
53     SECItem sigItem = {siBuffer, toUcharPtr(vec.sig.data()),
54                        static_cast<unsigned int>(vec.sig.size())};
55     ScopedSECItem decodedSigItem(
56         DSAU_DecodeDerSigToLen(&sigItem, SECKEY_SignatureLen(nssPubKey.get())));
57     if (!decodedSigItem) {
58       ASSERT_FALSE(vec.valid) << "Failed to decode DSA signature Error: "
59                               << PORT_ErrorToString(PORT_GetError()) << "\n";
60       return;
61     }
62 
63     Pkcs11SignatureTestParams params = {
64         DataBuffer(), pubKeyBuffer, DataBuffer(vec.msg.data(), vec.msg.size()),
65         DataBuffer(decodedSigItem.get()->data, decodedSigItem.get()->len)};
66     Pk11SignatureTest::Verify(params, (bool)vec.valid);
67   }
68 };
69 
70 class Pkcs11DsaTest : public Pkcs11DsaTestBase,
71                       public ::testing::WithParamInterface<DsaTestVector> {
72  public:
Pkcs11DsaTest()73   Pkcs11DsaTest() : Pkcs11DsaTestBase(GetParam().hash_oid) {}
74 };
75 
TEST_P(Pkcs11DsaTest,WycheproofVectors)76 TEST_P(Pkcs11DsaTest, WycheproofVectors) { Verify(GetParam()); }
77 
78 INSTANTIATE_TEST_SUITE_P(DsaTest, Pkcs11DsaTest,
79                          ::testing::ValuesIn(kDsaWycheproofVectors));
80 
81 }  // namespace nss_test
82