Skip to content

Commit

Permalink
[cryptotest] add test firmware handler and host-side driver for ecdsa…
Browse files Browse the repository at this point in the history
…/p256 verify operation

Signed-off-by: Ryan Torok <[email protected]>
  • Loading branch information
RyanTorok committed Jan 18, 2024
1 parent f38b01f commit 674090d
Show file tree
Hide file tree
Showing 12 changed files with 438 additions and 0 deletions.
20 changes: 20 additions & 0 deletions sw/device/tests/crypto/cryptotest/firmware/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,25 @@ cc_library(
],
)

cc_library(
name = "ecdsa",
srcs = ["ecdsa.c"],
hdrs = ["ecdsa.h"],
deps = [
"//sw/device/lib/base:memory",
"//sw/device/lib/base:status",
"//sw/device/lib/crypto/impl:ecc",
"//sw/device/lib/crypto/impl/ecc:p256_common",
"//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/tests/crypto/cryptotest/json:ecdsa_commands",
],
)

cc_library(
name = "aes_sca",
srcs = ["aes_sca.c"],
Expand Down Expand Up @@ -138,6 +157,7 @@ opentitan_binary(
],
deps = [
":aes",
":ecdsa",
":aes_sca",
":ibex_fi",
":kmac_sca",
Expand Down
137 changes: 137 additions & 0 deletions sw/device/tests/crypto/cryptotest/firmware/ecdsa.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
// Copyright lowRISC contributors.
// 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/ecc/p256_common.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/crypto/include/ecc.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/tests/crypto/cryptotest/json/ecdsa_commands.h"

status_t handle_ecdsa_block(ujson_t *uj) {
// Declare ECDSA parameter ujson deserializer types
cryptotest_ecdsa_operation_t uj_op;
cryptotest_ecdsa_hash_alg_t uj_hash_alg;
cryptotest_ecdsa_curve_t uj_curve;
cryptotest_ecdsa_message_t uj_message;
cryptotest_ecdsa_signature_t uj_signature;
cryptotest_ecdsa_coordinate_t uj_qx;
cryptotest_ecdsa_coordinate_t uj_qy;

// Deserialize ujson byte stream into ECDSA parameters
TRY(ujson_deserialize_cryptotest_ecdsa_operation_t(uj, &uj_op));
TRY(ujson_deserialize_cryptotest_ecdsa_hash_alg_t(uj, &uj_hash_alg));
TRY(ujson_deserialize_cryptotest_ecdsa_curve_t(uj, &uj_curve));
TRY(ujson_deserialize_cryptotest_ecdsa_message_t(uj, &uj_message));
TRY(ujson_deserialize_cryptotest_ecdsa_signature_t(uj, &uj_signature));
TRY(ujson_deserialize_cryptotest_ecdsa_coordinate_t(uj, &uj_qx));
TRY(ujson_deserialize_cryptotest_ecdsa_coordinate_t(uj, &uj_qy));

otcrypto_ecc_curve_type_t curve_type;
otcrypto_unblinded_key_t public_key;
p256_point_t pub_p256;

switch (uj_curve) {
case kCryptotestEcdsaCurveP256:
curve_type = kOtcryptoEccCurveTypeNistP256;
memset(pub_p256.x, 0, kP256CoordWords * 4);
memcpy(pub_p256.x, uj_qx.coordinate, uj_qx.coordinate_len);
memset(pub_p256.y, 0, kP256CoordWords * 4);
memcpy(pub_p256.y, uj_qy.coordinate, uj_qy.coordinate_len);
public_key.key_mode = kOtcryptoKeyModeEcdsa;
public_key.key_length = sizeof(p256_point_t);
public_key.key = (uint32_t *)&pub_p256;
break;
default:
LOG_ERROR("Unsupported ECC curve: %d", uj_curve);
return INVALID_ARGUMENT();
}
public_key.checksum = integrity_unblinded_checksum(&public_key);

otcrypto_ecc_curve_t elliptic_curve = {
.curve_type = curve_type,
// NULL because we use a named curve
.domain_parameter = NULL,
};
otcrypto_hash_mode_t mode;
switch (uj_hash_alg) {
case kCryptotestEcdsaHashAlgSha256:
mode = kOtcryptoHashModeSha256;
break;
case kCryptotestEcdsaHashAlgSha512:
mode = kOtcryptoHashModeSha512;
break;
case kCryptotestEcdsaHashAlgSha3_256:
mode = kOtcryptoHashModeSha3_256;
break;
case kCryptotestEcdsaHashAlgSha3_512:
mode = kOtcryptoHashModeSha3_512;
break;
default:
LOG_ERROR("Unrecognized ECDSA hash mode: %d", uj_hash_alg);
return INVALID_ARGUMENT();
}
uint8_t message_buf[ECDSA_CMD_MAX_MESSAGE_BYTES];
memcpy(message_buf, uj_message.input, uj_message.input_len);
const otcrypto_hash_digest_t message_digest = {
.mode = mode,
.len = uj_message.input_len / 4, // 32-bit words
.data = (uint32_t *)message_buf,
};
uint8_t signature_buf[ECDSA_CMD_MAX_SIGNATURE_BYTES];
switch (uj_op) {
case kCryptotestEcdsaOperationVerify: {
memcpy(signature_buf, uj_signature.signature, uj_signature.signature_len);
otcrypto_const_word32_buf_t signature = {
.data = (uint32_t *)signature_buf,
.len = uj_signature.signature_len,
};
hardened_bool_t verification_result = kHardenedBoolFalse;
otcrypto_status_t status =
otcrypto_ecdsa_verify(&public_key, &message_digest, signature,
&elliptic_curve, &verification_result);
if (status.value != kOk) {
return INTERNAL(status.value);
}
cryptotest_ecdsa_verify_output_t uj_output;
switch (verification_result) {
case kHardenedBoolFalse:
uj_output = kCryptotestEcdsaVerifyOutputFailure;
break;
case kHardenedBoolTrue:
uj_output = kCryptotestEcdsaVerifyOutputSuccess;
break;
default:
LOG_ERROR("Unexpected result value from otcrypto_ecdsa_verify: %d",
verification_result);
return INTERNAL();
}
RESP_OK(ujson_serialize_cryptotest_ecdsa_verify_output_t, uj, &uj_output);
break;
}
default:
LOG_ERROR("Unrecognized ECDSA operation: %d", uj_op);
return INVALID_ARGUMENT();
}
return OK_STATUS(0);
}

status_t handle_ecdsa(ujson_t *uj) {
ecdsa_subcommand_t cmd;
TRY(ujson_deserialize_ecdsa_subcommand_t(uj, &cmd));
switch (cmd) {
case kEcdsaSubcommandEcdsaBlock:
return handle_ecdsa_block(uj);
break;
default:
LOG_ERROR("Unrecognized ECDSA subcommand: %d", cmd);
return INVALID_ARGUMENT();
}
return OK_STATUS(0);
}
14 changes: 14 additions & 0 deletions sw/device/tests/crypto/cryptotest/firmware/ecdsa.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright lowRISC contributors.
// 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_ECDSA_H_
#define OPENTITAN_SW_DEVICE_TESTS_CRYPTO_CRYPTOTEST_FIRMWARE_ECDSA_H_

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

status_t handle_ecdsa_block(ujson_t *uj);
status_t handle_ecdsa(ujson_t *uj);

#endif // OPENTITAN_SW_DEVICE_TESTS_CRYPTO_CRYPTOTEST_FIRMWARE_ECDSA_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 @@ -18,6 +18,13 @@ cc_library(
deps = ["//sw/device/lib/ujson"],
)

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

cc_library(
name = "aes_sca_commands",
srcs = ["aes_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 @@ -13,6 +13,7 @@ extern "C" {

#define COMMAND(_, value) \
value(_, Aes) \
value(_, Ecdsa) \
value(_, AesSca) \
value(_, IbexFi) \
value(_, KmacSca) \
Expand Down
6 changes: 6 additions & 0 deletions sw/device/tests/crypto/cryptotest/json/ecdsa_commands.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#define UJSON_SERDE_IMPL 1
#include "ecdsa_commands.h"
62 changes: 62 additions & 0 deletions sw/device/tests/crypto/cryptotest/json/ecdsa_commands.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright lowRISC contributors.
// 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_ECDSA_COMMANDS_H_
#define OPENTITAN_SW_DEVICE_TESTS_CRYPTO_CRYPTOTEST_JSON_ECDSA_COMMANDS_H_
#include "sw/device/lib/ujson/ujson_derive.h"
#ifdef __cplusplus
extern "C" {
#endif

#define ECDSA_CMD_MAX_MESSAGE_BYTES 20
#define ECDSA_CMD_MAX_SIGNATURE_BYTES 72
#define ECDSA_CMD_MAX_COORDINATE_BYTES 33

// clang-format off

#define ECDSA_SUBCOMMAND(_, value) \
value(_, EcdsaBlock)
UJSON_SERDE_ENUM(EcdsaSubcommand, ecdsa_subcommand_t, ECDSA_SUBCOMMAND);

#define ECDSA_OPERATION(_, value) \
value(_, Verify)
UJSON_SERDE_ENUM(CryptotestEcdsaOperation, cryptotest_ecdsa_operation_t, ECDSA_OPERATION);

#define ECDSA_HASH_ALG(_, value) \
value(_, Sha256) \
value(_, Sha512) \
value(_, Sha3_256) \
value(_, Sha3_512)
UJSON_SERDE_ENUM(CryptotestEcdsaHashAlg, cryptotest_ecdsa_hash_alg_t, ECDSA_HASH_ALG);

#define ECDSA_MESSAGE(field, string) \
field(input, uint8_t, ECDSA_CMD_MAX_MESSAGE_BYTES) \
field(input_len, size_t)
UJSON_SERDE_STRUCT(CryptotestEcdsaMessage, cryptotest_ecdsa_message_t, ECDSA_MESSAGE);

#define ECDSA_SIGNATURE(field, string) \
field(signature, uint8_t, ECDSA_CMD_MAX_SIGNATURE_BYTES) \
field(signature_len, size_t)
UJSON_SERDE_STRUCT(CryptotestEcdsaSignature, cryptotest_ecdsa_signature_t, ECDSA_SIGNATURE);

#define ECDSA_CURVE(_, value) \
value(_, P256)
UJSON_SERDE_ENUM(CryptotestEcdsaCurve, cryptotest_ecdsa_curve_t, ECDSA_CURVE);

#define ECDSA_COORDINATE(field, string) \
field(coordinate, uint8_t, ECDSA_CMD_MAX_COORDINATE_BYTES) \
field(coordinate_len, size_t)
UJSON_SERDE_STRUCT(CryptotestEcdsaCoordinate, cryptotest_ecdsa_coordinate_t, ECDSA_COORDINATE);

#define ECDSA_VERIFY_OUTPUT(_, value) \
value(_, Success) \
value(_, Failure)
UJSON_SERDE_ENUM(CryptotestEcdsaVerifyOutput, cryptotest_ecdsa_verify_output_t, ECDSA_VERIFY_OUTPUT);

// clang-format on

#ifdef __cplusplus
}
#endif
#endif // OPENTITAN_SW_DEVICE_TESTS_CRYPTO_CRYPTOTEST_JSON_ECDSA_COMMANDS_H_
8 changes: 8 additions & 0 deletions sw/host/cryptotest/ujson_lib/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,28 @@ ujson_rust(
srcs = ["//sw/device/tests/crypto/cryptotest/json:aes_commands"],
)

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

rust_library(
name = "cryptotest_commands",
srcs = [
"src/aes_commands.rs",
"src/ecdsa_commands.rs",
"src/commands.rs",
"src/lib.rs",
],
compile_data = [
":commands_rust",
":aes_commands_rust",
":ecdsa_commands_rust",
],
rustc_env = {
"commands_loc": "$(execpath :commands_rust)",
"aes_commands_loc": "$(execpath :aes_commands_rust)",
"ecdsa_commands_loc": "$(execpath :ecdsa_commands_rust)",
},
deps = [
"//sw/host/opentitanlib",
Expand Down
4 changes: 4 additions & 0 deletions sw/host/cryptotest/ujson_lib/src/ecdsa_commands.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
include!(env!("ecdsa_commands_loc"));
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 @@ -2,4 +2,5 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
pub mod aes_commands;
pub mod ecdsa_commands;
pub mod commands;
25 changes: 25 additions & 0 deletions sw/host/tests/crypto/ecdsa_kat/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0

load("//rules:ujson.bzl", "ujson_rust")
load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_library")

package(default_visibility = ["//visibility:public"])

rust_binary(
name = "harness",
srcs = ["src/main.rs"],
deps = [
"//sw/host/cryptotest/ujson_lib:cryptotest_commands",
"//sw/host/opentitanlib",
"@crate_index//:anyhow",
"@crate_index//:arrayvec",
"@crate_index//:clap",
"@crate_index//:humantime",
"@crate_index//:num-bigint-dig",
"@crate_index//:log",
"@crate_index//:serde",
"@crate_index//:serde_json",
],
)
Loading

0 comments on commit 674090d

Please sign in to comment.