diff options
author | Tink Team <tink-dev@google.com> | 2021-09-02 04:39:25 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2021-09-02 04:40:08 -0700 |
commit | 18936dd1d06f58f98c6d45b95c6565e6de41093d (patch) | |
tree | 8521c426f78ec8d4e5663a6874cac717aa91a8aa /cc/experimental | |
parent | a36c68abfd597e6cde803c9a8df2b88e217278f8 (diff) | |
download | tink-18936dd1d06f58f98c6d45b95c6565e6de41093d.tar.gz |
Add subtle wrappers for sphincs signature schemes.
PiperOrigin-RevId: 394431421
Diffstat (limited to 'cc/experimental')
9 files changed, 1170 insertions, 69 deletions
diff --git a/cc/experimental/pqcrypto/signature/subtle/sphincs_sign.cc b/cc/experimental/pqcrypto/signature/subtle/sphincs_sign.cc new file mode 100644 index 000000000..4ee019276 --- /dev/null +++ b/cc/experimental/pqcrypto/signature/subtle/sphincs_sign.cc @@ -0,0 +1,73 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "tink/experimental/pqcrypto/signature/subtle/sphincs_sign.h" + +#include <string> +#include <utility> + +#include "absl/memory/memory.h" +#include "absl/strings/str_format.h" +#include "tink/experimental/pqcrypto/signature/subtle/sphincs_helper_pqclean.h" +#include "tink/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.h" +#include "tink/util/secret_data.h" +#include "tink/util/statusor.h" + +namespace crypto { +namespace tink { +namespace subtle { + +// static +util::StatusOr<std::unique_ptr<PublicKeySign>> SphincsSign::New( + SphincsPrivateKeyPqclean key) { + auto status = internal::CheckFipsCompatibility<SphincsSign>(); + if (!status.ok()) return status; + + util::Status key_size = ValidatePrivateKeySize(key.GetKey().size()); + if (!key_size.ok()) { + return key_size; + } + + return {absl::WrapUnique(new SphincsSign(std::move(key)))}; +} + +util::StatusOr<std::string> SphincsSign::Sign(absl::string_view data) const { + util::StatusOr<int32> key_size_index = + SphincsKeySizeToIndex(key_.GetKey().size()); + if (!key_size_index.ok()) { + return key_size_index.status(); + } + + size_t sig_length; + SphincsParamsPqclean params = key_.GetParams(); + const SphincsHelperPqclean &sphincs_helper_pqclean = + GetSphincsHelperPqclean(params.hash_type, params.variant, *key_size_index, + params.sig_length_type); + std::string signature(sphincs_helper_pqclean.GetSignatureLength(), '0'); + + if ((sphincs_helper_pqclean.Sign( + reinterpret_cast<uint8_t *>(signature.data()), &sig_length, + reinterpret_cast<const uint8_t *>(data.data()), data.size(), + reinterpret_cast<const uint8_t *>(key_.GetKey().data())) != 0)) { + return util::Status(util::error::INTERNAL, "Signing failed."); + } + + return signature; +} + +} // namespace subtle +} // namespace tink +} // namespace crypto diff --git a/cc/experimental/pqcrypto/signature/subtle/sphincs_sign.h b/cc/experimental/pqcrypto/signature/subtle/sphincs_sign.h new file mode 100644 index 000000000..3ff509624 --- /dev/null +++ b/cc/experimental/pqcrypto/signature/subtle/sphincs_sign.h @@ -0,0 +1,60 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_SPHINCS_SIGN_H_ +#define TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_SPHINCS_SIGN_H_ + +#include <memory> +#include <string> +#include <utility> + +#include "tink/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.h" +#include "tink/internal/fips_utils.h" +#include "tink/public_key_sign.h" +#include "tink/util/secret_data.h" +#include "tink/util/statusor.h" + +namespace crypto { +namespace tink { +namespace subtle { + +// Post-Quantum Signing using different variants of Sphincs stateless hash-based +// signature scheme +class SphincsSign : public PublicKeySign { + public: + static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = + crypto::tink::internal::FipsCompatibility::kNotFips; + + static crypto::tink::util::StatusOr<std::unique_ptr<PublicKeySign>> New( + SphincsPrivateKeyPqclean key); + + ~SphincsSign() override = default; + + // Computes the signature for 'data'. + crypto::tink::util::StatusOr<std::string> Sign( + absl::string_view data) const override; + + private: + explicit SphincsSign(SphincsPrivateKeyPqclean key) : key_(std::move(key)) {} + + const SphincsPrivateKeyPqclean key_; +}; + +} // namespace subtle +} // namespace tink +} // namespace crypto + +#endif // TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_SPHINCS_SIGN_H_ diff --git a/cc/experimental/pqcrypto/signature/subtle/sphincs_sign_test.cc b/cc/experimental/pqcrypto/signature/subtle/sphincs_sign_test.cc new file mode 100644 index 000000000..7ee91e6b6 --- /dev/null +++ b/cc/experimental/pqcrypto/signature/subtle/sphincs_sign_test.cc @@ -0,0 +1,359 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "tink/experimental/pqcrypto/signature/subtle/sphincs_sign.h" + +#include <string> +#include <utility> + +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include "absl/strings/str_cat.h" +#include "tink/config/tink_fips.h" +#include "tink/experimental/pqcrypto/signature/subtle/sphincs_helper_pqclean.h" +#include "tink/public_key_sign.h" +#include "tink/public_key_verify.h" +#include "tink/util/status.h" +#include "tink/util/statusor.h" +#include "tink/util/test_matchers.h" + +extern "C" { +#include "third_party/pqclean/crypto_sign/sphincs-haraka-128f-robust/aesni/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-haraka-128f-simple/aesni/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-haraka-128s-robust/aesni/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-haraka-128s-simple/aesni/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-haraka-192f-robust/aesni/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-haraka-192f-simple/aesni/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-haraka-192s-robust/aesni/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-haraka-192s-simple/aesni/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-haraka-256f-robust/aesni/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-haraka-256f-simple/aesni/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-haraka-256s-robust/aesni/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-haraka-256s-simple/aesni/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-sha256-128f-robust/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-sha256-128f-simple/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-sha256-128s-robust/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-sha256-128s-simple/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-sha256-192f-robust/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-sha256-192f-simple/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-sha256-192s-robust/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-sha256-192s-simple/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-sha256-256f-robust/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-sha256-256f-simple/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-sha256-256s-robust/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-sha256-256s-simple/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-shake256-128f-robust/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-shake256-128f-simple/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-shake256-128s-robust/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-shake256-128s-simple/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-shake256-192f-robust/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-shake256-192f-simple/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-shake256-192s-robust/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-shake256-192s-simple/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-shake256-256f-robust/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-shake256-256f-simple/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-shake256-256s-robust/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-shake256-256s-simple/avx2/api.h" +} + +namespace crypto { +namespace tink { +namespace subtle { + +namespace { + +struct SphincsTestCase { + std::string test_name; + SphincsHashType hash_type; + SphincsVariant variant; + SphincsSignatureLengthType sig_length_type; + int32_t private_key_size; + int32_t signature_length; +}; + +using ::crypto::tink::test::IsOk; +using ::crypto::tink::test::StatusIs; +using crypto::tink::util::Status; + +using SphincsSignTest = testing::TestWithParam<SphincsTestCase>; + +TEST_P(SphincsSignTest, SignatureLength) { + if (IsFipsModeEnabled()) { + GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; + } + + const SphincsTestCase& test_case = GetParam(); + + SphincsParamsPqclean params = { + .hash_type = test_case.hash_type, + .variant = test_case.variant, + .sig_length_type = test_case.sig_length_type, + .private_key_size = test_case.private_key_size, + }; + + // Generate sphincs key pair. + util::StatusOr<SphincsKeyPair> key_pair = GenerateSphincsKeyPair(params); + ASSERT_THAT(key_pair.status(), IsOk()); + + // Create a new signer. + util::StatusOr<std::unique_ptr<PublicKeySign>> signer = + SphincsSign::New(key_pair->GetPrivateKey()); + ASSERT_THAT(signer.status(), IsOk()); + + // Sign a message. + std::string message = "message to be signed"; + util::StatusOr<std::string> signature = (*signer)->Sign(message); + ASSERT_THAT(signature.status(), IsOk()); + + // Check signature size. + EXPECT_NE(*signature, message); + EXPECT_EQ((*signature).size(), test_case.signature_length); +} + +TEST_P(SphincsSignTest, NonDeterminism) { + if (IsFipsModeEnabled()) { + GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; + } + + const SphincsTestCase& test_case = GetParam(); + + SphincsParamsPqclean params = { + .hash_type = test_case.hash_type, + .variant = test_case.variant, + .sig_length_type = test_case.sig_length_type, + .private_key_size = test_case.private_key_size, + }; + + // Generate sphincs key pair. + util::StatusOr<SphincsKeyPair> key_pair = GenerateSphincsKeyPair(params); + ASSERT_THAT(key_pair.status(), IsOk()); + + // Create two signers based on same private key. + util::StatusOr<std::unique_ptr<PublicKeySign>> first_signer = + SphincsSign::New(key_pair->GetPrivateKey()); + ASSERT_THAT(first_signer.status(), IsOk()); + + util::StatusOr<std::unique_ptr<PublicKeySign>> second_signer = + SphincsSign::New(key_pair->GetPrivateKey()); + ASSERT_THAT(second_signer.status(), IsOk()); + + // Sign the same message twice, using the same private key. + std::string message = "message to be signed"; + util::StatusOr<std::string> first_signature = (*first_signer)->Sign(message); + ASSERT_THAT(first_signature.status(), IsOk()); + + util::StatusOr<std::string> second_signature = + (*second_signer)->Sign(message); + ASSERT_THAT(second_signature.status(), IsOk()); + + // Check signatures size. + EXPECT_NE(*first_signature, message); + EXPECT_EQ((*first_signature).size(), test_case.signature_length); + + EXPECT_NE(*second_signature, message); + EXPECT_EQ((*second_signature).size(), test_case.signature_length); + + // Check if signatures are equal. + EXPECT_NE(*first_signature, *second_signature); +} + +TEST_P(SphincsSignTest, FipsMode) { + if (!IsFipsModeEnabled()) { + GTEST_SKIP() << "Test assumes kOnlyUseFips."; + } + + const SphincsTestCase& test_case = GetParam(); + + SphincsParamsPqclean params = { + .hash_type = test_case.hash_type, + .variant = test_case.variant, + .sig_length_type = test_case.sig_length_type, + .private_key_size = test_case.private_key_size, + }; + + // Generate sphincs key pair. + util::StatusOr<SphincsKeyPair> key_pair = GenerateSphincsKeyPair(params); + ASSERT_THAT(key_pair.status(), IsOk()); + + // Create a new signer. + EXPECT_THAT(SphincsSign::New(key_pair->GetPrivateKey()).status(), + StatusIs(util::error::INTERNAL)); +} + +INSTANTIATE_TEST_SUITE_P( + SphincsSignTests, SphincsSignTest, + testing::ValuesIn<SphincsTestCase>( + {{"SPHINCSHARAKA128FROBUST", SphincsHashType::HARAKA, + SphincsVariant::ROBUST, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_BYTES}, + {"SPHINCSHARAKA128SROBUST", SphincsHashType::HARAKA, + SphincsVariant::ROBUST, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_BYTES}, + {"SPHINCSHARAKA128FSIMPLE", SphincsHashType::HARAKA, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_BYTES}, + {"SPHINCSHARAKA128SSIMPLE", SphincsHashType::HARAKA, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_BYTES}, + + {"SPHINCSHARAKA192FROBUST", SphincsHashType::HARAKA, + SphincsVariant::ROBUST, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_BYTES}, + {"SPHINCSHARAKA192SROBUST", SphincsHashType::HARAKA, + SphincsVariant::ROBUST, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_BYTES}, + {"SPHINCSHARAKA192FSIMPLE", SphincsHashType::HARAKA, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_BYTES}, + {"SPHINCSHARAKA192SSIMPLE", SphincsHashType::HARAKA, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_BYTES}, + + {"SPHINCSHARAKA256FROBUST", SphincsHashType::HARAKA, + SphincsVariant::ROBUST, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_BYTES}, + {"SPHINCSHARAKA256SROBUST", SphincsHashType::HARAKA, + SphincsVariant::ROBUST, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_BYTES}, + {"SPHINCSHARAKA256FSIMPLE", SphincsHashType::HARAKA, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_BYTES}, + {"SPHINCSHARAKA256SSIMPLE", SphincsHashType::HARAKA, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_BYTES}, + + {"SPHINCSSHA256128FROBUST", SphincsHashType::SHA256, + SphincsVariant::ROBUST, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHA256128SROBUST", SphincsHashType::SHA256, + SphincsVariant::ROBUST, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHA256128FSIMPLE", SphincsHashType::SHA256, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHA256128SSIMPLE", SphincsHashType::SHA256, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_CRYPTO_BYTES}, + + {"SPHINCSSHA256192FROBUST", SphincsHashType::SHA256, + SphincsVariant::ROBUST, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHA256192SROBUST", SphincsHashType::SHA256, + SphincsVariant::ROBUST, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHA256192FSIMPLE", SphincsHashType::SHA256, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHA256192SSIMPLE", SphincsHashType::SHA256, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_CRYPTO_BYTES}, + + {"SPHINCSSHA256256FROBUST", SphincsHashType::SHA256, + SphincsVariant::ROBUST, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHA256256SROBUST", SphincsHashType::SHA256, + SphincsVariant::ROBUST, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHA256256FSIMPLE", SphincsHashType::SHA256, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHA256256SSIMPLE", SphincsHashType::SHA256, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_CRYPTO_BYTES}, + + {"SPHINCSSHAKE256128FROBUST", SphincsHashType::SHAKE256, + SphincsVariant::ROBUST, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHAKE256128SROBUST", SphincsHashType::SHAKE256, + SphincsVariant::ROBUST, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHAKE256128FSIMPLE", SphincsHashType::SHAKE256, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHAKE256128SSIMPLE", SphincsHashType::SHAKE256, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_CRYPTO_BYTES}, + + {"SPHINCSSHAKE256192FROBUST", SphincsHashType::SHAKE256, + SphincsVariant::ROBUST, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHAKE256192SROBUST", SphincsHashType::SHAKE256, + SphincsVariant::ROBUST, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHAKE256192FSIMPLE", SphincsHashType::SHAKE256, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHAKE256192SSIMPLE", SphincsHashType::SHAKE256, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_BYTES}, + + {"SPHINCSSHAKE256256FROBUST", SphincsHashType::SHAKE256, + SphincsVariant::ROBUST, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHAKE256256SROBUST", SphincsHashType::SHAKE256, + SphincsVariant::ROBUST, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHAKE256256FSIMPLE", SphincsHashType::SHAKE256, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHAKE256256SSIMPLE", SphincsHashType::SHAKE256, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_CRYPTO_BYTES}}), + [](const testing::TestParamInfo<SphincsSignTest::ParamType>& info) { + return info.param.test_name; + }); + +} // namespace + +} // namespace subtle +} // namespace tink +} // namespace crypto diff --git a/cc/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.cc b/cc/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.cc index 52bc84128..956c5500b 100644 --- a/cc/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.cc +++ b/cc/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.cc @@ -25,18 +25,14 @@ #include "tink/util/secret_data.h" #include "tink/util/statusor.h" -// Definitions of the three possible sphincs key sizes. -#define SPHINCSKEYSIZE64 64 -#define SPHINCSKEYSIZE96 96 -#define SPHINCSKEYSIZE128 128 - namespace crypto { namespace tink { namespace subtle { crypto::tink::util::StatusOr<SphincsKeyPair> GenerateSphincsKeyPair( - SphincsParams params) { - util::Status key_size_status = ValidateKeySize(params.private_key_size); + SphincsParamsPqclean params) { + util::Status key_size_status = + ValidatePrivateKeySize(params.private_key_size); if (!key_size_status.ok()) { return key_size_status; } @@ -65,35 +61,51 @@ crypto::tink::util::StatusOr<SphincsKeyPair> GenerateSphincsKeyPair( util::SecretData private_key_data = util::SecretDataFromStringView(private_key); - SphincsKeyPair key_pair(SphincsPrivateKeyPqclean{private_key_data}, - SphincsPublicKeyPqclean{public_key}); + SphincsKeyPair key_pair(SphincsPrivateKeyPqclean{private_key_data, params}, + SphincsPublicKeyPqclean{public_key, params}); return key_pair; } -crypto::tink::util::Status ValidateKeySize(int32 key_size) { +crypto::tink::util::Status ValidatePrivateKeySize(int32 key_size) { + switch (key_size) { + case kSphincsPrivateKeySize64: + case kSphincsPrivateKeySize96: + case kSphincsPrivateKeySize128: + return util::Status::OK; + default: + return util::Status( + util::error::INVALID_ARGUMENT, + absl::StrFormat("Invalid private key size (%d). " + "The only valid sizes are %d, %d, %d.", + key_size, kSphincsPrivateKeySize64, + kSphincsPrivateKeySize96, kSphincsPrivateKeySize128)); + } +} + +crypto::tink::util::Status ValidatePublicKeySize(int32 key_size) { switch (key_size) { - case SPHINCSKEYSIZE64: - case SPHINCSKEYSIZE96: - case SPHINCSKEYSIZE128: + case kSphincsPublicKeySize32: + case kSphincsPublicKeySize48: + case kSphincsPublicKeySize64: return util::Status::OK; default: return util::Status( util::error::INVALID_ARGUMENT, absl::StrFormat("Invalid private key size (%d). " "The only valid sizes are %d, %d, %d.", - key_size, SPHINCSKEYSIZE64, SPHINCSKEYSIZE96, - SPHINCSKEYSIZE128)); + key_size, kSphincsPublicKeySize32, + kSphincsPublicKeySize48, kSphincsPublicKeySize64)); } } crypto::tink::util::StatusOr<int32> SphincsKeySizeToIndex(int32 key_size) { switch (key_size) { - case SPHINCSKEYSIZE64: + case kSphincsPrivateKeySize64: return 0; - case SPHINCSKEYSIZE96: + case kSphincsPrivateKeySize96: return 1; - case SPHINCSKEYSIZE128: + case kSphincsPrivateKeySize128: return 2; default: return util::Status(util::error::INVALID_ARGUMENT, "Invalid key size"); diff --git a/cc/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.h b/cc/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.h index fef40401b..38f5f0fc5 100644 --- a/cc/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.h +++ b/cc/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.h @@ -29,6 +29,16 @@ namespace crypto { namespace tink { namespace subtle { +// The three possible sphincs private key sizes. +const int kSphincsPrivateKeySize64 = 64; +const int kSphincsPrivateKeySize96 = 96; +const int kSphincsPrivateKeySize128 = 128; + +// The three possible sphincs public key sizes. +const int kSphincsPublicKeySize32 = 32; +const int kSphincsPublicKeySize48 = 48; +const int kSphincsPublicKeySize64 = 64; + enum SphincsHashType { HARAKA = 0, SHA256 = 1, @@ -45,78 +55,79 @@ enum SphincsSignatureLengthType { S = 1, }; +struct SphincsParamsPqclean { + SphincsHashType hash_type; + SphincsVariant variant; + SphincsSignatureLengthType sig_length_type; + int32 private_key_size; +}; + +// Representation of the Sphincs private key. class SphincsPrivateKeyPqclean { public: - explicit SphincsPrivateKeyPqclean(util::SecretData key_data) - : private_key_data_(std::move(key_data)) {} + explicit SphincsPrivateKeyPqclean(util::SecretData key_data, + SphincsParamsPqclean params) + : private_key_data_(std::move(key_data)), params_(std::move(params)) {} SphincsPrivateKeyPqclean(const SphincsPrivateKeyPqclean& other) = default; SphincsPrivateKeyPqclean& operator=(const SphincsPrivateKeyPqclean& other) = default; - const util::SecretData& Get() const { return private_key_data_; } + const util::SecretData& GetKey() const { return private_key_data_; } + const SphincsParamsPqclean& GetParams() const { return params_; } private: const util::SecretData private_key_data_; + const SphincsParamsPqclean params_; }; +// Representation of the Sphincs public key. class SphincsPublicKeyPqclean { public: - explicit SphincsPublicKeyPqclean(std::string key_data) - : public_key_data_(std::move(key_data)) {} + SphincsPublicKeyPqclean(std::string key_data, SphincsParamsPqclean params) + : public_key_data_(std::move(key_data)), params_(std::move(params)) {} SphincsPublicKeyPqclean(const SphincsPublicKeyPqclean& other) = default; SphincsPublicKeyPqclean& operator=(const SphincsPublicKeyPqclean& other) = default; - const std::string& Get() const { return public_key_data_; } + const std::string& GetKey() const { return public_key_data_; } + const SphincsParamsPqclean& GetParams() const { return params_; } private: const std::string public_key_data_; + const SphincsParamsPqclean params_; }; class SphincsKeyPair { public: SphincsKeyPair(SphincsPrivateKeyPqclean private_key, SphincsPublicKeyPqclean public_key) - : private_key_(private_key), public_key_(public_key) {} + : private_key_(std::move(private_key)), + public_key_(std::move(public_key)) {} SphincsKeyPair(const SphincsKeyPair& other) = default; - SphincsKeyPair& operator=(const SphincsKeyPair& other) = - default; + SphincsKeyPair& operator=(const SphincsKeyPair& other) = default; const SphincsPrivateKeyPqclean& GetPrivateKey() const { return private_key_; } const SphincsPublicKeyPqclean& GetPublicKey() const { return public_key_; } private: - SphincsPrivateKeyPqclean private_key_; - SphincsPublicKeyPqclean public_key_; -}; - -struct SphincsParams { - SphincsHashType hash_type; - SphincsVariant variant; - SphincsSignatureLengthType sig_length_type; - int32 private_key_size; - - SphincsParams(SphincsHashType hash_type_, SphincsVariant variant_, - int32 private_key_size_, - SphincsSignatureLengthType sig_length_type_) { - hash_type = hash_type_; - variant = variant_; - private_key_size = private_key_size_; - sig_length_type = sig_length_type_; - } + const SphincsPrivateKeyPqclean private_key_; + const SphincsPublicKeyPqclean public_key_; }; // This is an utility function that generates a new Sphincs key pair based on // Sphincs specific parameters. This function is expected to be called from // a key manager class. crypto::tink::util::StatusOr<SphincsKeyPair> GenerateSphincsKeyPair( - SphincsParams params); + SphincsParamsPqclean params); + +// Validates whether the private key size is safe to use for sphincs signature. +crypto::tink::util::Status ValidatePrivateKeySize(int32 key_size); -// Validates whether 'key_size' is safe to use for sphincs signature. -crypto::tink::util::Status ValidateKeySize(int32 key_size); +// Validates whether the public key size is safe to use for sphincs signature. +crypto::tink::util::Status ValidatePublicKeySize(int32 key_size); // Convert the sphincs private key size to the appropiate index in the // pqclean functions array. diff --git a/cc/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils_test.cc b/cc/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils_test.cc index c5ee6a9dd..928b77d07 100644 --- a/cc/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils_test.cc +++ b/cc/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils_test.cc @@ -66,11 +66,6 @@ extern "C" { #include "third_party/pqclean/crypto_sign/sphincs-shake256-256s-simple/avx2/api.h" } -// Definitions of the three possible sphincs key sizes. -#define SPHINCSKEYSIZE64 64 -#define SPHINCSKEYSIZE96 96 -#define SPHINCSKEYSIZE128 128 - namespace crypto { namespace tink { namespace subtle { @@ -92,41 +87,64 @@ using SphincsUtilsTest = testing::TestWithParam<SphincsUtilsTestCase>; TEST_P(SphincsUtilsTest, SphincsKeysLength) { const SphincsUtilsTestCase& test_case = GetParam(); - SphincsParams params(test_case.hash_type, test_case.variant, - test_case.private_key_size, test_case.sig_length_type); + SphincsParamsPqclean params = { + .hash_type = test_case.hash_type, + .variant = test_case.variant, + .sig_length_type = test_case.sig_length_type, + .private_key_size = test_case.private_key_size, + }; // Generate sphincs key pair. util::StatusOr<SphincsKeyPair> key_pair = GenerateSphincsKeyPair(params); ASSERT_THAT(key_pair.status(), IsOk()); // Check keys size. - EXPECT_EQ(key_pair->GetPrivateKey().Get().size(), test_case.private_key_size); - EXPECT_EQ(key_pair->GetPublicKey().Get().size(), test_case.public_key_size); + EXPECT_EQ(key_pair->GetPrivateKey().GetKey().size(), + test_case.private_key_size); + EXPECT_EQ(key_pair->GetPublicKey().GetKey().size(), + test_case.public_key_size); } TEST_P(SphincsUtilsTest, DifferentContent) { const SphincsUtilsTestCase& test_case = GetParam(); - SphincsParams params(test_case.hash_type, test_case.variant, - test_case.private_key_size, test_case.sig_length_type); + SphincsParamsPqclean params = { + .hash_type = test_case.hash_type, + .variant = test_case.variant, + .sig_length_type = test_case.sig_length_type, + .private_key_size = test_case.private_key_size, + }; // Generate sphincs key pair. util::StatusOr<SphincsKeyPair> key_pair = GenerateSphincsKeyPair(params); ASSERT_THAT(key_pair.status(), IsOk()); // Check keys content is different. - EXPECT_NE(util::SecretDataAsStringView(key_pair->GetPrivateKey().Get()), - key_pair->GetPublicKey().Get()); + EXPECT_NE(util::SecretDataAsStringView(key_pair->GetPrivateKey().GetKey()), + key_pair->GetPublicKey().GetKey()); +} + +TEST(SphincsUtilsTest, InvalidPrivateKeySize) { + for (int keysize = 0; keysize <= kSphincsPrivateKeySize128; keysize++) { + if (keysize == kSphincsPrivateKeySize64 || + keysize == kSphincsPrivateKeySize96 || + keysize == kSphincsPrivateKeySize128) { + // Valid key size. + continue; + } + EXPECT_FALSE(ValidatePrivateKeySize(keysize).ok()); + } } -TEST(SphincsUtilsTest, InvalidKeySize) { - for (int keysize = 0; keysize <= SPHINCSKEYSIZE128; keysize++) { - if (keysize == SPHINCSKEYSIZE64 || keysize == SPHINCSKEYSIZE96 || - keysize == SPHINCSKEYSIZE128) { +TEST(SphincsUtilsTest, InvalidPublicKeySize) { + for (int keysize = 0; keysize <= kSphincsPrivateKeySize128; keysize++) { + if (keysize == kSphincsPublicKeySize32 || + keysize == kSphincsPublicKeySize48 || + keysize == kSphincsPublicKeySize64) { // Valid key size. continue; } - EXPECT_FALSE(ValidateKeySize(keysize).ok()); + EXPECT_FALSE(ValidatePublicKeySize(keysize).ok()); } } @@ -197,7 +215,7 @@ INSTANTIATE_TEST_SUITE_P( PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256128SSIMPLE", SphincsHashType::SHA256, - SphincsVariant::ROBUST, SphincsSignatureLengthType::S, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::S, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES}, @@ -240,7 +258,7 @@ INSTANTIATE_TEST_SUITE_P( PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256128SROBUST", SphincsHashType::SHAKE256, - SphincsVariant::ROBUST, SphincsSignatureLengthType::F, + SphincsVariant::ROBUST, SphincsSignatureLengthType::S, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256128FSIMPLE", SphincsHashType::SHAKE256, @@ -265,7 +283,7 @@ INSTANTIATE_TEST_SUITE_P( PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256192SSIMPLE", SphincsHashType::SHAKE256, - SphincsVariant::ROBUST, SphincsSignatureLengthType::S, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::S, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES}, diff --git a/cc/experimental/pqcrypto/signature/subtle/sphincs_verify.cc b/cc/experimental/pqcrypto/signature/subtle/sphincs_verify.cc new file mode 100644 index 000000000..2906601db --- /dev/null +++ b/cc/experimental/pqcrypto/signature/subtle/sphincs_verify.cc @@ -0,0 +1,74 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "tink/experimental/pqcrypto/signature/subtle/sphincs_verify.h" + +#include <string> +#include <utility> + +#include "absl/memory/memory.h" +#include "absl/strings/str_format.h" +#include "tink/experimental/pqcrypto/signature/subtle/sphincs_helper_pqclean.h" +#include "tink/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.h" +#include "tink/util/secret_data.h" +#include "tink/util/statusor.h" + +namespace crypto { +namespace tink { +namespace subtle { + +// static +util::StatusOr<std::unique_ptr<PublicKeyVerify>> SphincsVerify::New( + SphincsPublicKeyPqclean public_key) { + auto status = internal::CheckFipsCompatibility<SphincsVerify>(); + if (!status.ok()) return status; + + util::Status key_size = ValidatePublicKeySize(public_key.GetKey().size()); + if (!key_size.ok()) { + return key_size; + } + + return {absl::WrapUnique<SphincsVerify>( + new SphincsVerify(std::move(public_key)))}; +} + +util::Status SphincsVerify::Verify(absl::string_view signature, + absl::string_view data) const { + SphincsParamsPqclean params = key_.GetParams(); + util::StatusOr<int32> key_size_index = + SphincsKeySizeToIndex(params.private_key_size); + if (!key_size_index.ok()) { + return key_size_index.status(); + } + + const SphincsHelperPqclean &sphincs_helper_pqclean = + GetSphincsHelperPqclean(params.hash_type, params.variant, *key_size_index, + params.sig_length_type); + + if ((sphincs_helper_pqclean.Verify( + reinterpret_cast<const uint8_t *>(signature.data()), signature.size(), + reinterpret_cast<const uint8_t *>(data.data()), data.size(), + reinterpret_cast<const uint8_t *>(key_.GetKey().data()))) != 0) { + return util::Status(util::error::INVALID_ARGUMENT, + "Signature is not valid."); + } + + return util::Status::OK; +} + +} // namespace subtle +} // namespace tink +} // namespace crypto diff --git a/cc/experimental/pqcrypto/signature/subtle/sphincs_verify.h b/cc/experimental/pqcrypto/signature/subtle/sphincs_verify.h new file mode 100644 index 000000000..c48cce18a --- /dev/null +++ b/cc/experimental/pqcrypto/signature/subtle/sphincs_verify.h @@ -0,0 +1,56 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_SPHINCS_VERIFY_H_ +#define TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_SPHINCS_VERIFY_H_ + +#include <memory> +#include <string> +#include <utility> + +#include "tink/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.h" +#include "tink/internal/fips_utils.h" +#include "tink/public_key_verify.h" +#include "tink/util/secret_data.h" +#include "tink/util/statusor.h" + +namespace crypto { +namespace tink { +namespace subtle { + +class SphincsVerify : public PublicKeyVerify { + public: + static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = + crypto::tink::internal::FipsCompatibility::kNotFips; + + static crypto::tink::util::StatusOr<std::unique_ptr<PublicKeyVerify>> New( + SphincsPublicKeyPqclean key); + + // Verifies that 'signature' is a digital signature for 'data'. + crypto::tink::util::Status Verify(absl::string_view signature, + absl::string_view data) const override; + + private: + explicit SphincsVerify(SphincsPublicKeyPqclean key) : key_(std::move(key)) {} + + const SphincsPublicKeyPqclean key_; +}; + +} // namespace subtle +} // namespace tink +} // namespace crypto + +#endif // TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_SPHINCS_VERIFY_H_ diff --git a/cc/experimental/pqcrypto/signature/subtle/sphincs_verify_test.cc b/cc/experimental/pqcrypto/signature/subtle/sphincs_verify_test.cc new file mode 100644 index 000000000..869c314df --- /dev/null +++ b/cc/experimental/pqcrypto/signature/subtle/sphincs_verify_test.cc @@ -0,0 +1,438 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "tink/experimental/pqcrypto/signature/subtle/sphincs_verify.h" + +#include <string> +#include <utility> + +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include "absl/strings/str_cat.h" +#include "tink/config/tink_fips.h" +#include "tink/experimental/pqcrypto/signature/subtle/sphincs_helper_pqclean.h" +#include "tink/experimental/pqcrypto/signature/subtle/sphincs_sign.h" +#include "tink/public_key_sign.h" +#include "tink/public_key_verify.h" +#include "tink/util/status.h" +#include "tink/util/statusor.h" +#include "tink/util/test_matchers.h" + +extern "C" { +#include "third_party/pqclean/crypto_sign/sphincs-haraka-128f-robust/aesni/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-haraka-128f-simple/aesni/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-haraka-128s-robust/aesni/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-haraka-128s-simple/aesni/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-haraka-192f-robust/aesni/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-haraka-192f-simple/aesni/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-haraka-192s-robust/aesni/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-haraka-192s-simple/aesni/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-haraka-256f-robust/aesni/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-haraka-256f-simple/aesni/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-haraka-256s-robust/aesni/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-haraka-256s-simple/aesni/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-sha256-128f-robust/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-sha256-128f-simple/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-sha256-128s-robust/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-sha256-128s-simple/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-sha256-192f-robust/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-sha256-192f-simple/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-sha256-192s-robust/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-sha256-192s-simple/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-sha256-256f-robust/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-sha256-256f-simple/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-sha256-256s-robust/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-sha256-256s-simple/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-shake256-128f-robust/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-shake256-128f-simple/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-shake256-128s-robust/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-shake256-128s-simple/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-shake256-192f-robust/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-shake256-192f-simple/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-shake256-192s-robust/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-shake256-192s-simple/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-shake256-256f-robust/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-shake256-256f-simple/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-shake256-256s-robust/avx2/api.h" +#include "third_party/pqclean/crypto_sign/sphincs-shake256-256s-simple/avx2/api.h" +} + +namespace crypto { +namespace tink { +namespace subtle { + +namespace { + +struct SphincsTestCase { + std::string test_name; + SphincsHashType hash_type; + SphincsVariant variant; + SphincsSignatureLengthType sig_length_type; + int32_t private_key_size; + int32_t signature_length; +}; + +using ::crypto::tink::test::IsOk; +using ::crypto::tink::test::StatusIs; +using crypto::tink::util::Status; + +using SphincsVerifyTest = testing::TestWithParam<SphincsTestCase>; + +TEST_P(SphincsVerifyTest, BasicSignVerify) { + if (IsFipsModeEnabled()) { + GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; + } + + const SphincsTestCase& test_case = GetParam(); + + SphincsParamsPqclean params = { + .hash_type = test_case.hash_type, + .variant = test_case.variant, + .sig_length_type = test_case.sig_length_type, + .private_key_size = test_case.private_key_size, + }; + + // Generate sphincs key pair. + util::StatusOr<SphincsKeyPair> key_pair = GenerateSphincsKeyPair(params); + ASSERT_THAT(key_pair.status(), IsOk()); + + // Create a new signer. + util::StatusOr<std::unique_ptr<PublicKeySign>> signer = + SphincsSign::New(key_pair->GetPrivateKey()); + ASSERT_THAT(signer.status(), IsOk()); + + // Sign a message. + std::string message = "message to be signed"; + util::StatusOr<std::string> signature = (*signer)->Sign(message); + ASSERT_THAT(signature.status(), IsOk()); + + // Create a new verifier. + absl::StatusOr<std::unique_ptr<PublicKeyVerify>> verifier = + SphincsVerify::New(key_pair->GetPublicKey()); + ASSERT_THAT(verifier.status(), IsOk()); + + // Verify signature. + Status status = (*verifier)->Verify(*signature, message); + EXPECT_THAT(status, IsOk()); +} + +TEST_P(SphincsVerifyTest, FailsWithWrongSignature) { + if (IsFipsModeEnabled()) { + GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; + } + + const SphincsTestCase& test_case = GetParam(); + + SphincsParamsPqclean params = { + .hash_type = test_case.hash_type, + .variant = test_case.variant, + .sig_length_type = test_case.sig_length_type, + .private_key_size = test_case.private_key_size, + }; + + // Generate sphincs key pair. + util::StatusOr<SphincsKeyPair> key_pair = GenerateSphincsKeyPair(params); + ASSERT_THAT(key_pair.status(), IsOk()); + + // Create a new signer. + util::StatusOr<std::unique_ptr<PublicKeySign>> signer = + SphincsSign::New(key_pair->GetPrivateKey()); + ASSERT_THAT(signer.status(), IsOk()); + + // Sign a message. + std::string message = "message to be signed"; + util::StatusOr<std::string> signature = (*signer)->Sign(message); + ASSERT_THAT(signature.status(), IsOk()); + + // Create a new verifier. + absl::StatusOr<std::unique_ptr<PublicKeyVerify>> verifier = + SphincsVerify::New(key_pair->GetPublicKey()); + ASSERT_THAT(verifier.status(), IsOk()); + + // Verify signature. + Status status = + (*verifier)->Verify(*signature + "some trailing data", message); + EXPECT_FALSE(status.ok()); +} + +TEST_P(SphincsVerifyTest, FailsWithWrongMessage) { + if (IsFipsModeEnabled()) { + GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; + } + + const SphincsTestCase& test_case = GetParam(); + + SphincsParamsPqclean params = { + .hash_type = test_case.hash_type, + .variant = test_case.variant, + .sig_length_type = test_case.sig_length_type, + .private_key_size = test_case.private_key_size, + }; + + // Generate sphincs key pair. + util::StatusOr<SphincsKeyPair> key_pair = GenerateSphincsKeyPair(params); + ASSERT_THAT(key_pair.status(), IsOk()); + + // Create a new signer. + util::StatusOr<std::unique_ptr<PublicKeySign>> signer = + SphincsSign::New(key_pair->GetPrivateKey()); + ASSERT_THAT(signer.status(), IsOk()); + + // Sign a message. + std::string message = "message to be signed"; + util::StatusOr<std::string> signature = (*signer)->Sign(message); + ASSERT_THAT(signature.status(), IsOk()); + + // Create a new verifier. + absl::StatusOr<std::unique_ptr<PublicKeyVerify>> verifier = + SphincsVerify::New(key_pair->GetPublicKey()); + ASSERT_THAT(verifier.status(), IsOk()); + + // Verify signature. + Status status = (*verifier)->Verify(*signature, "some bad message"); + EXPECT_FALSE(status.ok()); +} + +TEST_P(SphincsVerifyTest, FailsWithBytesFlipped) { + if (IsFipsModeEnabled()) { + GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; + } + + const SphincsTestCase& test_case = GetParam(); + + SphincsParamsPqclean params = { + .hash_type = test_case.hash_type, + .variant = test_case.variant, + .sig_length_type = test_case.sig_length_type, + .private_key_size = test_case.private_key_size, + }; + + // Generate sphincs key pair. + util::StatusOr<SphincsKeyPair> key_pair = GenerateSphincsKeyPair(params); + ASSERT_THAT(key_pair.status(), IsOk()); + + // Create a new signer. + util::StatusOr<std::unique_ptr<PublicKeySign>> signer = + SphincsSign::New(key_pair->GetPrivateKey()); + ASSERT_THAT(signer.status(), IsOk()); + + // Sign a message. + std::string message = "message to be signed"; + util::StatusOr<std::string> signature = (*signer)->Sign(message); + ASSERT_THAT(signature.status(), IsOk()); + + // Create a new verifier. + absl::StatusOr<std::unique_ptr<PublicKeyVerify>> verifier = + SphincsVerify::New(key_pair->GetPublicKey()); + ASSERT_THAT(verifier.status(), IsOk()); + + // Invalidate one signature byte. + (*signature)[0] ^= 1; + + // Verify signature. + Status status = (*verifier)->Verify(*signature, message); + EXPECT_FALSE(status.ok()); +} + +TEST_P(SphincsVerifyTest, FipsMode) { + if (!IsFipsModeEnabled()) { + GTEST_SKIP() << "Test assumes kOnlyUseFips."; + } + + const SphincsTestCase& test_case = GetParam(); + + SphincsParamsPqclean params = { + .hash_type = test_case.hash_type, + .variant = test_case.variant, + .sig_length_type = test_case.sig_length_type, + .private_key_size = test_case.private_key_size, + }; + + // Generate sphincs key pair. + util::StatusOr<SphincsKeyPair> key_pair = GenerateSphincsKeyPair(params); + ASSERT_THAT(key_pair.status(), IsOk()); + + // Create a new signer. + EXPECT_THAT(SphincsVerify::New(key_pair->GetPublicKey()).status(), + StatusIs(util::error::INTERNAL)); +} + +// TODO(ioannanedelcu): Add test with testvectors. + +INSTANTIATE_TEST_SUITE_P( + SphincsVerifyTests, SphincsVerifyTest, + testing::ValuesIn<SphincsTestCase>( + {{"SPHINCSHARAKA128FROBUST", SphincsHashType::HARAKA, + SphincsVariant::ROBUST, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_BYTES}, + {"SPHINCSHARAKA128SROBUST", SphincsHashType::HARAKA, + SphincsVariant::ROBUST, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_BYTES}, + {"SPHINCSHARAKA128FSIMPLE", SphincsHashType::HARAKA, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_BYTES}, + {"SPHINCSHARAKA128SSIMPLE", SphincsHashType::HARAKA, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_BYTES}, + + {"SPHINCSHARAKA192FROBUST", SphincsHashType::HARAKA, + SphincsVariant::ROBUST, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_BYTES}, + {"SPHINCSHARAKA192SROBUST", SphincsHashType::HARAKA, + SphincsVariant::ROBUST, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_BYTES}, + {"SPHINCSHARAKA192FSIMPLE", SphincsHashType::HARAKA, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_BYTES}, + {"SPHINCSHARAKA192SSIMPLE", SphincsHashType::HARAKA, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_BYTES}, + + {"SPHINCSHARAKA256FROBUST", SphincsHashType::HARAKA, + SphincsVariant::ROBUST, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_BYTES}, + {"SPHINCSHARAKA256SROBUST", SphincsHashType::HARAKA, + SphincsVariant::ROBUST, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_BYTES}, + {"SPHINCSHARAKA256FSIMPLE", SphincsHashType::HARAKA, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_BYTES}, + {"SPHINCSHARAKA256SSIMPLE", SphincsHashType::HARAKA, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_BYTES}, + + {"SPHINCSSHA256128FROBUST", SphincsHashType::SHA256, + SphincsVariant::ROBUST, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHA256128SROBUST", SphincsHashType::SHA256, + SphincsVariant::ROBUST, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHA256128FSIMPLE", SphincsHashType::SHA256, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHA256128SSIMPLE", SphincsHashType::SHA256, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_CRYPTO_BYTES}, + + {"SPHINCSSHA256192FROBUST", SphincsHashType::SHA256, + SphincsVariant::ROBUST, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHA256192SROBUST", SphincsHashType::SHA256, + SphincsVariant::ROBUST, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHA256192FSIMPLE", SphincsHashType::SHA256, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHA256192SSIMPLE", SphincsHashType::SHA256, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_CRYPTO_BYTES}, + + {"SPHINCSSHA256256FROBUST", SphincsHashType::SHA256, + SphincsVariant::ROBUST, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHA256256SROBUST", SphincsHashType::SHA256, + SphincsVariant::ROBUST, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHA256256FSIMPLE", SphincsHashType::SHA256, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHA256256SSIMPLE", SphincsHashType::SHA256, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_CRYPTO_BYTES}, + + {"SPHINCSSHAKE256128FROBUST", SphincsHashType::SHAKE256, + SphincsVariant::ROBUST, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHAKE256128SROBUST", SphincsHashType::SHAKE256, + SphincsVariant::ROBUST, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHAKE256128FSIMPLE", SphincsHashType::SHAKE256, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHAKE256128SSIMPLE", SphincsHashType::SHAKE256, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_CRYPTO_BYTES}, + + {"SPHINCSSHAKE256192FROBUST", SphincsHashType::SHAKE256, + SphincsVariant::ROBUST, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHAKE256192SROBUST", SphincsHashType::SHAKE256, + SphincsVariant::ROBUST, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHAKE256192FSIMPLE", SphincsHashType::SHAKE256, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHAKE256192SSIMPLE", SphincsHashType::SHAKE256, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_BYTES}, + + {"SPHINCSSHAKE256256FROBUST", SphincsHashType::SHAKE256, + SphincsVariant::ROBUST, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHAKE256256SROBUST", SphincsHashType::SHAKE256, + SphincsVariant::ROBUST, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHAKE256256FSIMPLE", SphincsHashType::SHAKE256, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::F, + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_CRYPTO_BYTES}, + {"SPHINCSSHAKE256256SSIMPLE", SphincsHashType::SHAKE256, + SphincsVariant::SIMPLE, SphincsSignatureLengthType::S, + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES, + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_CRYPTO_BYTES}}), + [](const testing::TestParamInfo<SphincsVerifyTest::ParamType>& info) { + return info.param.test_name; + }); + +} // namespace + +} // namespace subtle +} // namespace tink +} // namespace crypto |