Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[cryptotest] Test harness for SPHINCS+ verify operation w/ SHA-2 #21681

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions sw/device/tests/crypto/cryptotest/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,25 @@ cryptotest(
test_vectors = KMAC_TESTVECTOR_TARGETS,
)

SPHINCSPLUS_TESTVECTOR_TARGETS = [
"//sw/host/cryptotest/testvectors/data:{}".format(target)
for target in [
"rsp_sphincsplus_sha256_128s_simple_json",
]
]

SPHINCSPLUS_TESTVECTOR_ARGS = " ".join([
"--sphincsplus-json=\"$(rootpath {})\"".format(target)
for target in SPHINCSPLUS_TESTVECTOR_TARGETS
])

cryptotest(
name = "sphincsplus_kat",
test_args = SPHINCSPLUS_TESTVECTOR_ARGS,
test_harness = "//sw/host/tests/crypto/sphincsplus_kat:harness",
test_vectors = SPHINCSPLUS_TESTVECTOR_TARGETS,
)

# Use the following command to run the entire test suite in a given target:
# $ export OT_EXEC_ENV=silicon_owner_sival_rom_ext
# $ bazel test --//signing:token=//signing/tokens:cloud_kms \
Expand Down Expand Up @@ -392,5 +411,6 @@ test_suite(
":sha512_kat",
":shake128_kat",
":shake256_kat",
":sphincsplus_kat",
],
)
20 changes: 19 additions & 1 deletion sw/device/tests/crypto/cryptotest/firmware/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,31 @@ cc_library(
"//sw/device/lib/crypto/impl:integrity",
"//sw/device/lib/crypto/impl:keyblob",
"//sw/device/lib/crypto/impl:mac",
"//sw/device/lib/crypto/include:datatypes",
"//sw/device/lib/runtime:log",
"//sw/device/lib/testing/test_framework:ujson_ottf",
"//sw/device/lib/ujson",
"//sw/device/tests/crypto/cryptotest/json:hmac_commands",
],
)

cc_library(
name = "sphincsplus",
srcs = ["sphincsplus.c"],
hdrs = ["sphincsplus.h"],
deps = [
"//sw/device/lib/base:memory",
"//sw/device/lib/base:status",
"//sw/device/lib/crypto/impl:integrity",
"//sw/device/lib/crypto/impl:keyblob",
"//sw/device/lib/crypto/include:datatypes",
"//sw/device/lib/runtime:log",
"//sw/device/lib/testing/test_framework:ujson_ottf",
"//sw/device/lib/ujson",
"//sw/device/silicon_creator/lib/sigverify/sphincsplus:verify",
"//sw/device/tests/crypto/cryptotest/json:sphincsplus_commands",
],
)

cc_library(
name = "kmac",
srcs = ["kmac.c"],
Expand Down Expand Up @@ -347,6 +364,7 @@ FIRMWARE_DEPS = [
":otbn_fi",
":prng_sca",
":sha3_sca",
":sphincsplus",
":trigger_sca",
"//sw/device/lib/base:csr",
"//sw/device/lib/base:status",
Expand Down
5 changes: 5 additions & 0 deletions sw/device/tests/crypto/cryptotest/firmware/firmware.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "sw/device/tests/crypto/cryptotest/json/otbn_fi_commands.h"
#include "sw/device/tests/crypto/cryptotest/json/prng_sca_commands.h"
#include "sw/device/tests/crypto/cryptotest/json/sha3_sca_commands.h"
#include "sw/device/tests/crypto/cryptotest/json/sphincsplus_commands.h"
#include "sw/device/tests/crypto/cryptotest/json/trigger_sca_commands.h"

// Include handlers
Expand All @@ -43,6 +44,7 @@
#include "otbn_fi.h"
#include "prng_sca.h"
#include "sha3_sca.h"
#include "sphincsplus.h"
#include "trigger_sca.h"

OTTF_DEFINE_TEST_CONFIG(.enable_uart_flow_control = true);
Expand Down Expand Up @@ -73,6 +75,9 @@ status_t process_cmd(ujson_t *uj) {
case kCryptotestCommandKmac:
RESP_ERR(uj, handle_kmac(uj));
break;
case kCryptotestCommandSphincsPlus:
RESP_ERR(uj, handle_sphincsplus(uj));
break;
case kCryptotestCommandAesSca:
RESP_ERR(uj, handle_aes_sca(uj));
break;
Expand Down
99 changes: 99 additions & 0 deletions sw/device/tests/crypto/cryptotest/firmware/sphincsplus.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#include "sw/device/lib/base/memory.h"
#include "sw/device/lib/base/status.h"
#include "sw/device/lib/crypto/impl/integrity.h"
#include "sw/device/lib/crypto/impl/keyblob.h"
#include "sw/device/lib/crypto/include/datatypes.h"
#include "sw/device/lib/runtime/log.h"
#include "sw/device/lib/testing/test_framework/ujson_ottf.h"
#include "sw/device/lib/ujson/ujson.h"
#include "sw/device/silicon_creator/lib/sigverify/sphincsplus/verify.h"
#include "sw/device/tests/crypto/cryptotest/json/sphincsplus_commands.h"

status_t handle_sphincsplus_verify(ujson_t *uj) {
// Declare SPHINCS+ parameter ujson deserializer types
cryptotest_sphincsplus_hash_alg_t uj_hash_alg;
cryptotest_sphincsplus_public_key_t uj_public_key;
cryptotest_sphincsplus_message_t uj_message;
cryptotest_sphincsplus_signature_t uj_signature;

// Deserialize ujson byte stream into SPHINCS+ parameters
TRY(ujson_deserialize_cryptotest_sphincsplus_hash_alg_t(uj, &uj_hash_alg));
TRY(ujson_deserialize_cryptotest_sphincsplus_public_key_t(uj,
&uj_public_key));
TRY(ujson_deserialize_cryptotest_sphincsplus_message_t(uj, &uj_message));
TRY(ujson_deserialize_cryptotest_sphincsplus_signature_t(uj, &uj_signature));

if (uj_public_key.public_len != kSpxVerifyPkBytes) {
LOG_ERROR("Incorrect public key length: (expected = %d, got = %d)",
kSpxVerifyPkBytes, uj_public_key.public_len);
return INVALID_ARGUMENT();
}
if (uj_signature.signature_len != kSpxVerifySigBytes) {
LOG_ERROR("Incorrect signature length: (expected = %d, got = %d)",
kSpxVerifySigBytes, uj_signature.signature_len);
return INVALID_ARGUMENT();
}

switch (uj_hash_alg) {
case kCryptotestSphincsPlusHashAlgSha256:
break;
case kCryptotestSphincsPlusHashAlgShake256:
LOG_ERROR("SPHINCS+ SHAKE-256 is currently unsupported.");
return INVALID_ARGUMENT();
default:
LOG_ERROR("Unrecognized SPHINCS+ hash mode: %d", uj_hash_alg);
return INVALID_ARGUMENT();
}
uint32_t exp_root[kSpxVerifyRootNumWords];
spx_public_key_root((uint32_t *)uj_public_key.public, exp_root);
uint32_t act_root[kSpxVerifyRootNumWords];
rom_error_t error =
spx_verify((uint32_t *)uj_signature.signature, NULL, 0, NULL, 0, NULL, 0,
(uint8_t *)uj_message.message, uj_message.message_len,
(uint32_t *)uj_public_key.public, act_root);
cryptotest_sphincsplus_verify_output_t uj_output;
switch (error) {
case kErrorOk:
uj_output = kCryptotestSphincsPlusVerifyOutputSuccess;
for (size_t i = 0; i < kSpxVerifyRootNumWords; i++) {
if (exp_root[i] != act_root[i]) {
uj_output = kCryptotestSphincsPlusVerifyOutputFailure;
break;
}
}
RESP_OK(ujson_serialize_cryptotest_sphincsplus_verify_output_t, uj,
&uj_output);
break;
case kErrorSigverifyBadSpxSignature:
OT_FALLTHROUGH_INTENDED;
case kErrorSigverifyBadSpxKey:
uj_output = kCryptotestSphincsPlusVerifyOutputFailure;
// Respond "failure" if the IUT reports an invalid argument
RESP_OK(ujson_serialize_cryptotest_sphincsplus_verify_output_t, uj,
&uj_output);
break;
default:
LOG_ERROR(
"Unexpected error value returned from spx_verify: "
"0x%x",
error);
return INTERNAL();
}
return OK_STATUS(0);
}

status_t handle_sphincsplus(ujson_t *uj) {
cryptotest_sphincsplus_operation_t uj_op;
TRY(ujson_deserialize_cryptotest_sphincsplus_operation_t(uj, &uj_op));
switch (uj_op) {
case kCryptotestSphincsPlusOperationVerify:
return handle_sphincsplus_verify(uj);
default:
LOG_ERROR("Unsupported SPHINCS+ operation: %d", uj_op);
return INVALID_ARGUMENT();
}
}
13 changes: 13 additions & 0 deletions sw/device/tests/crypto/cryptotest/firmware/sphincsplus.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#ifndef OPENTITAN_SW_DEVICE_TESTS_CRYPTO_CRYPTOTEST_FIRMWARE_SPHINCSPLUS_H_
#define OPENTITAN_SW_DEVICE_TESTS_CRYPTO_CRYPTOTEST_FIRMWARE_SPHINCSPLUS_H_

#include "sw/device/lib/base/status.h"
#include "sw/device/lib/ujson/ujson.h"

status_t handle_sphincsplus(ujson_t *uj);

#endif // OPENTITAN_SW_DEVICE_TESTS_CRYPTO_CRYPTOTEST_FIRMWARE_SPHINCSPLUS_H_
7 changes: 7 additions & 0 deletions sw/device/tests/crypto/cryptotest/json/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,13 @@ cc_library(
deps = ["//sw/device/lib/ujson"],
)

cc_library(
name = "sphincsplus_commands",
srcs = ["sphincsplus_commands.c"],
hdrs = ["sphincsplus_commands.h"],
deps = ["//sw/device/lib/ujson"],
)

cc_library(
name = "trigger_sca_commands",
srcs = ["trigger_sca_commands.c"],
Expand Down
1 change: 1 addition & 0 deletions sw/device/tests/crypto/cryptotest/json/commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ extern "C" {
value(_, OtbnFi) \
value(_, PrngSca) \
value(_, Sha3Sca) \
value(_, SphincsPlus) \
value(_, TriggerSca)
UJSON_SERDE_ENUM(CryptotestCommand, cryptotest_cmd_t, COMMAND);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#define UJSON_SERDE_IMPL 1
#include "sphincsplus_commands.h"
52 changes: 52 additions & 0 deletions sw/device/tests/crypto/cryptotest/json/sphincsplus_commands.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#ifndef OPENTITAN_SW_DEVICE_TESTS_CRYPTO_CRYPTOTEST_JSON_SPHINCSPLUS_COMMANDS_H_
#define OPENTITAN_SW_DEVICE_TESTS_CRYPTO_CRYPTOTEST_JSON_SPHINCSPLUS_COMMANDS_H_
#include "sw/device/lib/ujson/ujson_derive.h"
#ifdef __cplusplus
extern "C" {
#endif

#define SPHINCSPLUS_CMD_MAX_MESSAGE_BYTES 3300
#define SPHINCSPLUS_CMD_MAX_SIGNATURE_BYTES 7856
#define SPHINCSPLUS_CMD_MAX_PUBLIC_KEY_BYTES 32

// clang-format off

#define SPHINCSPLUS_OPERATION(_, value) \
value(_, Verify)
UJSON_SERDE_ENUM(CryptotestSphincsPlusOperation, cryptotest_sphincsplus_operation_t, SPHINCSPLUS_OPERATION);

#define SPHINCSPLUS_HASH_ALG(_, value) \
value(_, Sha256) \
value(_, Shake256)
UJSON_SERDE_ENUM(CryptotestSphincsPlusHashAlg, cryptotest_sphincsplus_hash_alg_t, SPHINCSPLUS_HASH_ALG);

#define SPHINCSPLUS_MESSAGE(field, string) \
field(message, uint8_t, SPHINCSPLUS_CMD_MAX_MESSAGE_BYTES) \
field(message_len, size_t)
UJSON_SERDE_STRUCT(CryptotestSphincsPlusMessage, cryptotest_sphincsplus_message_t, SPHINCSPLUS_MESSAGE);

#define SPHINCSPLUS_SIGNATURE(field, string) \
field(signature, uint8_t, SPHINCSPLUS_CMD_MAX_SIGNATURE_BYTES) \
field(signature_len, size_t)
UJSON_SERDE_STRUCT(CryptotestSphincsPlusSignature, cryptotest_sphincsplus_signature_t, SPHINCSPLUS_SIGNATURE);

#define SPHINCSPLUS_PUBLIC_KEY(field, string) \
field(public, uint8_t, SPHINCSPLUS_CMD_MAX_PUBLIC_KEY_BYTES) \
field(public_len, size_t)
UJSON_SERDE_STRUCT(CryptotestSphincsPlusPublicKey, cryptotest_sphincsplus_public_key_t, SPHINCSPLUS_PUBLIC_KEY);

#define SPHINCSPLUS_VERIFY_OUTPUT(_, value) \
value(_, Success) \
value(_, Failure)
UJSON_SERDE_ENUM(CryptotestSphincsPlusVerifyOutput, cryptotest_sphincsplus_verify_output_t, SPHINCSPLUS_VERIFY_OUTPUT);

// clang-format on

#ifdef __cplusplus
}
#endif
#endif // OPENTITAN_SW_DEVICE_TESTS_CRYPTO_CRYPTOTEST_JSON_SPHINCSPLUS_COMMANDS_H_
44 changes: 25 additions & 19 deletions sw/host/cryptotest/testvectors/data/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -714,25 +714,31 @@ WYCHEPROOF_RSA_PSS_SUFFIXES = {
]
]

run_binary(
name = "rsp_sphincsplus_shake256_128s_simple_json",
srcs = [
"//sw/host/cryptotest/testvectors/data/schemas:sphincsplus_schema.json",
"@sphincsplus_kat//:sphincs-shake256-128s-simple/PQCsignKAT_64.rsp",
],
outs = [":rsp_sphincsplus_shake256_128s_simple.json"],
args = [
"--src",
"$(location @sphincsplus_kat//:sphincs-shake256-128s-simple/PQCsignKAT_64.rsp)",
"--dst",
"$(location :rsp_sphincsplus_shake256_128s_simple.json)",
"--schema",
"$(location //sw/host/cryptotest/testvectors/data/schemas:sphincsplus_schema.json)",
"--hash_alg",
"shake-256",
],
tool = "//sw/host/cryptotest/testvectors/parsers:rsp_sphincsplus_parser",
)
[
run_binary(
name = "rsp_sphincsplus_{}_128s_simple_json".format(hash_alg),
srcs = [
"//sw/host/cryptotest/testvectors/data/schemas:sphincsplus_schema.json",
"@sphincsplus_{h}_kat//:sphincs-{h}-128s-simple/PQCsignKAT_64.rsp".format(h = hash_alg),
],
outs = [":rsp_sphincsplus_{}_128s_simple.json".format(hash_alg)],
args = [
"--src",
"$(location @sphincsplus_{h}_kat//:sphincs-{h}-128s-simple/PQCsignKAT_64.rsp)".format(h = hash_alg),
"--dst",
"$(location :rsp_sphincsplus_{}_128s_simple.json)".format(hash_alg),
"--schema",
"$(location //sw/host/cryptotest/testvectors/data/schemas:sphincsplus_schema.json)",
"--hash_alg",
hash_arg,
],
tool = "//sw/host/cryptotest/testvectors/parsers:rsp_sphincsplus_parser",
)
for (hash_alg, hash_arg) in [
("sha256", "sha-256"),
("shake256", "shake-256"),
]
]

run_binary(
name = "hjson_kmac",
Expand Down
8 changes: 8 additions & 0 deletions sw/host/cryptotest/ujson_lib/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ ujson_rust(
srcs = ["//sw/device/tests/crypto/cryptotest/json:kmac_commands"],
)

ujson_rust(
name = "sphincsplus_commands_rust",
srcs = ["//sw/device/tests/crypto/cryptotest/json:sphincsplus_commands"],
)

rust_library(
name = "cryptotest_commands",
srcs = [
Expand All @@ -59,6 +64,7 @@ rust_library(
"src/hmac_commands.rs",
"src/kmac_commands.rs",
"src/lib.rs",
"src/sphincsplus_commands.rs",
],
compile_data = [
":commands_rust",
Expand All @@ -69,6 +75,7 @@ rust_library(
":hash_commands_rust",
":hmac_commands_rust",
":kmac_commands_rust",
":sphincsplus_commands_rust",
],
rustc_env = {
"commands_loc": "$(execpath :commands_rust)",
Expand All @@ -79,6 +86,7 @@ rust_library(
"hash_commands_loc": "$(execpath :hash_commands_rust)",
"hmac_commands_loc": "$(execpath :hmac_commands_rust)",
"kmac_commands_loc": "$(execpath :kmac_commands_rust)",
"sphincsplus_commands_loc": "$(execpath :sphincsplus_commands_rust)",
},
deps = [
"//sw/host/opentitanlib",
Expand Down
1 change: 1 addition & 0 deletions sw/host/cryptotest/ujson_lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ pub mod ecdsa_commands;
pub mod hash_commands;
pub mod hmac_commands;
pub mod kmac_commands;
pub mod sphincsplus_commands;
4 changes: 4 additions & 0 deletions sw/host/cryptotest/ujson_lib/src/sphincsplus_commands.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
include!(env!("sphincsplus_commands_loc"));
Loading
Loading