aboutsummaryrefslogtreecommitdiff
path: root/cc/experimental
diff options
context:
space:
mode:
authorTink Team <tink-dev@google.com>2021-09-02 04:39:25 -0700
committerCopybara-Service <copybara-worker@google.com>2021-09-02 04:40:08 -0700
commit18936dd1d06f58f98c6d45b95c6565e6de41093d (patch)
tree8521c426f78ec8d4e5663a6874cac717aa91a8aa /cc/experimental
parenta36c68abfd597e6cde803c9a8df2b88e217278f8 (diff)
downloadtink-18936dd1d06f58f98c6d45b95c6565e6de41093d.tar.gz
Add subtle wrappers for sphincs signature schemes.
PiperOrigin-RevId: 394431421
Diffstat (limited to 'cc/experimental')
-rw-r--r--cc/experimental/pqcrypto/signature/subtle/sphincs_sign.cc73
-rw-r--r--cc/experimental/pqcrypto/signature/subtle/sphincs_sign.h60
-rw-r--r--cc/experimental/pqcrypto/signature/subtle/sphincs_sign_test.cc359
-rw-r--r--cc/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.cc48
-rw-r--r--cc/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.h71
-rw-r--r--cc/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils_test.cc60
-rw-r--r--cc/experimental/pqcrypto/signature/subtle/sphincs_verify.cc74
-rw-r--r--cc/experimental/pqcrypto/signature/subtle/sphincs_verify.h56
-rw-r--r--cc/experimental/pqcrypto/signature/subtle/sphincs_verify_test.cc438
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