Skip to content

Commit

Permalink
[test] Enable passing arguments to the functest harness
Browse files Browse the repository at this point in the history
Move the required args to the end and name them the "test commands."
Pass the test commands via an environment variable, and place them at
the end of the invocation.

This makes the test commands unable to be overridden by test_arg
arguments, and simultaneously, it allows the user to specify test_arg
arguments on the bazel command line to modify arguments to opentitantool
and friends. Those test_arg arguments can override or supplement the
test harness's arguments provided by the bazel rule.

Signed-off-by: Alexander Williams <[email protected]>
Signed-off-by: Miguel Osorio <[email protected]>
  • Loading branch information
a-will authored and moidx committed Aug 30, 2022
1 parent 92638b9 commit e0468a5
Show file tree
Hide file tree
Showing 6 changed files with 618 additions and 4 deletions.
57 changes: 53 additions & 4 deletions sw/device/lib/crypto/drivers/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ cc_library(
],
)

cc_library(
name = "kmac_test_vectors",
srcs = ["kmac_test_vectors.c"],
hdrs = ["kmac_test_vectors.h"],
deps = [
":kmac",
],
)

opentitan_functest(
name = "kmac_test",
srcs = ["kmac_test.c"],
Expand Down Expand Up @@ -65,11 +74,51 @@ opentitan_functest(
)

cc_library(
name = "kmac_test_vectors",
srcs = ["kmac_test_vectors.c"],
hdrs = ["kmac_test_vectors.h"],
name = "entropy",
srcs = ["entropy.c"],
hdrs = ["entropy.h"],
deps = [
":kmac",
"//hw/ip/csrng/data:csrng_regs",
"//hw/top_earlgrey/sw/autogen:top_earlgrey",
"//sw/device/lib/base:abs_mmio",
"//sw/device/lib/base:bitfield",
"//sw/device/lib/base:hardened",
"//sw/device/lib/base:macros",
"//sw/device/lib/base:memory",
"//sw/device/lib/base:status",
],
)

cc_library(
name = "entropy_kat",
srcs = ["entropy_kat.c"],
hdrs = ["entropy_kat.h"],
deps = [
":entropy",
"//hw/ip/csrng/data:csrng_regs",
"//hw/top_earlgrey/sw/autogen:top_earlgrey",
"//sw/device/lib/base:abs_mmio",
"//sw/device/lib/base:bitfield",
"//sw/device/lib/base:macros",
"//sw/device/lib/base:memory",
"//sw/device/lib/base:status",
"//sw/device/lib/runtime:log",
],
)

opentitan_functest(
name = "entropy_test",
srcs = ["entropy_test.c"],
verilator = verilator_params(
timeout = "long",
),
deps = [
":entropy",
":entropy_kat",
"//sw/device/lib/base:macros",
"//sw/device/lib/base:memory",
"//sw/device/lib/testing/test_framework:check",
"//sw/device/lib/testing/test_framework:ottf_main",
],
)

Expand Down
186 changes: 186 additions & 0 deletions sw/device/lib/crypto/drivers/entropy.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
// 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/crypto/drivers/entropy.h"

#include "sw/device/lib/base/abs_mmio.h"
#include "sw/device/lib/base/bitfield.h"
#include "sw/device/lib/base/memory.h"

#include "csrng_regs.h" // Generated
#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"

enum {
kBaseCsrng = TOP_EARLGREY_CSRNG_BASE_ADDR,

/**
* CSRNG genbits buffer size in uint32_t words.
*/
kEntropyCsrngBitsBufferNumWords = 4,
};

/**
* Supported CSRNG application commands.
* See https://docs.opentitan.org/hw/ip/csrng/doc/#command-header for
* details.
*/
// TODO(#14542): Harden csrng/edn command fields.
typedef enum entropy_csrng_op {
kEntropyDrbgOpInstantiate = 1,
kEntropyDrbgOpReseed = 2,
kEntropyDrbgOpGenerate = 3,
kEntropyDrbgOpUpdate = 4,
kEntropyDrbgOpUnisntantiate = 5,
} entropy_csrng_op_t;

/**
* CSRNG application interface command header parameters.
*/
typedef struct entropy_csrng_cmd {
/**
* Application command ID.
*/
entropy_csrng_op_t id;
/**
* Entropy source enable.
*
* Mapped to flag0 in the hardware command interface.
*/
hardened_bool_t disable_trng_input;
const entropy_seed_material_t *seed_material;
/**
* Generate length. Specified as number of 128bit blocks.
*/
uint32_t generate_len;
} entropy_csrng_cmd_t;

#define ENTROPY_CMD(m, i) ((bitfield_field32_t){.mask = m, .index = i})

OT_WARN_UNUSED_RESULT
static status_t csrng_send_app_cmd(uint32_t reg_address,
entropy_csrng_cmd_t cmd) {
uint32_t reg;
bool cmd_ready;
bool cmd_error;
do {
reg = abs_mmio_read32(kBaseCsrng + CSRNG_SW_CMD_STS_REG_OFFSET);
cmd_ready = bitfield_bit32_read(reg, CSRNG_SW_CMD_STS_CMD_RDY_BIT);
} while (!cmd_ready);

// The application command header is not specified as a register in the
// hardware specification, so the fields are mapped here by hand. The
// command register also accepts arbitrary 32bit data.
static const uint32_t kAppCmdBitFlag0 = 8;
static const bitfield_field32_t kAppCmdFieldCmdId = ENTROPY_CMD(0xf, 0);
static const bitfield_field32_t kAppCmdFieldCmdLen = ENTROPY_CMD(0xf, 4);
static const bitfield_field32_t kAppCmdFieldGlen = ENTROPY_CMD(0x7ffff, 12);

uint32_t cmd_len = cmd.seed_material == NULL ? 0 : cmd.seed_material->len;

if (cmd_len & ~kAppCmdFieldCmdLen.mask) {
return INTERNAL();
}

// TODO: Consider removing this since the driver will be constructing these
// commands internally.
// Ensure the `seed_material` array is word-aligned, so it can be loaded to a
// CPU register with natively aligned loads.
if (cmd.seed_material != NULL &&
misalignment32_of((uintptr_t)cmd.seed_material->data) != 0) {
return INTERNAL();
}

// Build and write application command header.
reg = bitfield_field32_write(0, kAppCmdFieldCmdId, cmd.id);
reg = bitfield_field32_write(reg, kAppCmdFieldCmdLen, cmd_len);
reg = bitfield_field32_write(reg, kAppCmdFieldGlen, cmd.generate_len);

if (launder32(cmd.disable_trng_input) == kHardenedBoolTrue) {
reg = bitfield_bit32_write(reg, kAppCmdBitFlag0, true);
}

abs_mmio_write32(reg_address, reg);

for (size_t i = 0; i < cmd_len; ++i) {
abs_mmio_write32(reg_address, cmd.seed_material->data[i]);
}
return OK_STATUS();
}

status_t entropy_csrng_instantiate(
hardened_bool_t disable_trng_input,
const entropy_seed_material_t *seed_material) {
return csrng_send_app_cmd(kBaseCsrng + CSRNG_CMD_REQ_REG_OFFSET,
(entropy_csrng_cmd_t){
.id = kEntropyDrbgOpInstantiate,
.disable_trng_input = disable_trng_input,
.seed_material = seed_material,
.generate_len = 0,
});
}

status_t entropy_csrng_reseed(hardened_bool_t disable_trng_input,
const entropy_seed_material_t *seed_material) {
return csrng_send_app_cmd(kBaseCsrng + CSRNG_CMD_REQ_REG_OFFSET,
(entropy_csrng_cmd_t){
.id = kEntropyDrbgOpReseed,
.disable_trng_input = disable_trng_input,
.seed_material = seed_material,
.generate_len = 0,
});
}

status_t entropy_csrng_update(const entropy_seed_material_t *seed_material) {
return csrng_send_app_cmd(kBaseCsrng + CSRNG_CMD_REQ_REG_OFFSET,
(entropy_csrng_cmd_t){
.id = kEntropyDrbgOpUpdate,
.seed_material = seed_material,
.generate_len = 0,
});
}

status_t entropy_csrng_generate_start(
const entropy_seed_material_t *seed_material, size_t len) {
// Round up the number of 128bit blocks. Aligning with respect to uint32_t.
// TODO(#6112): Consider using a canonical reference for alignment operations.
const uint32_t num_128bit_blocks = (len + 3) / 4;
return csrng_send_app_cmd(kBaseCsrng + CSRNG_CMD_REQ_REG_OFFSET,
(entropy_csrng_cmd_t){
.id = kEntropyDrbgOpGenerate,
.seed_material = seed_material,
.generate_len = num_128bit_blocks,
});
}

status_t entropy_csrng_generate_data_get(uint32_t *buf, size_t len) {
for (size_t i = 0; i < len; ++i) {
// Block until there is more data available in the genbits buffer. CSRNG
// generates data in 128bit chunks (i.e. 4 words).
static_assert(kEntropyCsrngBitsBufferNumWords == 4,
"kEntropyCsrngBitsBufferNumWords must be a power of 2.");
if (i & (kEntropyCsrngBitsBufferNumWords - 1)) {
uint32_t reg;
do {
reg = abs_mmio_read32(kBaseCsrng + CSRNG_GENBITS_VLD_REG_OFFSET);
} while (!bitfield_bit32_read(reg, CSRNG_GENBITS_VLD_GENBITS_VLD_BIT));
}
buf[i] = abs_mmio_read32(kBaseCsrng + CSRNG_GENBITS_REG_OFFSET);
}
return OK_STATUS();
}

status_t entropy_csrng_generate(const entropy_seed_material_t *seed_material,
uint32_t *buf, size_t len) {
TRY(entropy_csrng_generate_start(seed_material, len));
return entropy_csrng_generate_data_get(buf, len);
}

status_t entropy_csrng_uninstantiate(void) {
return csrng_send_app_cmd(kBaseCsrng + CSRNG_CMD_REQ_REG_OFFSET,
(entropy_csrng_cmd_t){
.id = kEntropyDrbgOpUpdate,
.seed_material = NULL,
.generate_len = 0,
});
}
139 changes: 139 additions & 0 deletions sw/device/lib/crypto/drivers/entropy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
// 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_LIB_CRYPTO_DRIVERS_ENTROPY_H_
#define OPENTITAN_SW_DEVICE_LIB_CRYPTO_DRIVERS_ENTROPY_H_

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#include "sw/device/lib/base/hardened.h"
#include "sw/device/lib/base/macros.h"
#include "sw/device/lib/base/status.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
* Seed material as specified in NIST SP 800-90Ar1 section 10.2.1.3.1. Up to 12
* words of seed material can be provided using this interface.
*/
typedef struct entropy_seed_material {
/**
* Number of words set in `data`. CSRNG will extend the `data` to zeros if the
* provided value is less than 12.
*/
size_t len;
/**
* Seed material in unsigned word format.
*/
uint32_t data[12];
} entropy_seed_material_t;

/**
* Instantiate the SW CSRNG with a new seed value.
*
* SW CSRNG refers to the CSRNG hardware instance available for software use.
*
* @param disable_trng_input Set to kHardenedTrue to disable the random seed
* data provided by hardware. This enables the use of the CSRNG in deterministic
* mode.
* @param seed_material Data used to seed the CSRNG. XOR'ed entropy provided by
* hardware when `disable_trng_input` is set to `kHardenedFalse`, otherwise used
* directly as the seed.
* @return Operation status in `status_t` format.
*/
OT_WARN_UNUSED_RESULT
status_t entropy_csrng_instantiate(
hardened_bool_t disable_trng_input,
const entropy_seed_material_t *seed_material);

/**
* Reseed the SW CSRNG.
*
* @param disable_trng_intput Set to kHardenedTrue to disable the entropy
* provided by hardware.
* @param seed_material Data used to reseed the CSRNG. XOR'ed with entropy
* provided by hardware when `disable_trng_input` is set to `kHardenedFalse`,
* otherwise used directly as the seed
* @return Operation status in `status_t` format.
*/
OT_WARN_UNUSED_RESULT
status_t entropy_csrng_reseed(hardened_bool_t disable_trng_input,
const entropy_seed_material_t *seed_material);

/**
* Update the SW CSRNG state.
*
* This command does not update the CSRNG internal reseed counter.
*
* @param seed_material Additional data used in the CSRNG update operation.
* There is no additional entropy loaded from hardware.
* @return Operation status in `status_t` format.
*/
OT_WARN_UNUSED_RESULT
status_t entropy_csrng_update(const entropy_seed_material_t *seed_material);

/**
* Request data from the SW CSRNG.
*
* Use `entropy_csrng_generate_data_get()` to read the data from the CSRNG
* output buffer.
*
* See `entropy_csrng_generate()` for requesting and reading the CSRNG output in
* a single call.
*
* @param seed_material Additional data used in the CSRNG generate operation.
* There is no additional entropy loaded from hardware.
* @param len Number of uint32_t words to generate.
* @return Operation status in `status_t` format.
*/
OT_WARN_UNUSED_RESULT
status_t entropy_csrng_generate_start(
const entropy_seed_material_t *seed_material, size_t len);

/**
* Read SW CSRNG output.
*
* Requires the `entropy_csrng_generate_start()` function to be called in
* advance, otherwise the function will block indefinitely.
*
* @param buf A buffer to fill with words from the CSRNG output buffer.
* @param len The number of words to read into `buf`.
* @return Operation status in `status_t` format.
*/
OT_WARN_UNUSED_RESULT
status_t entropy_csrng_generate_data_get(uint32_t *buf, size_t len);

/**
* Request and read data from the SW CSRNG.
*
* @param seed_material Additional data used in the CSRNG generate operation.
* There is not additional entropy loaded from hardware.
* @param buf A buffer to fill with words from the CSRNG output buffer.
* @param len The number of words to read into `buf`.
* @return Operation status in `status_t` format.
*/
OT_WARN_UNUSED_RESULT
status_t entropy_csrng_generate(const entropy_seed_material_t *seed_material,
uint32_t *buf, size_t len);

/**
* Uninstantiate the SW CSRNG.
*
* Thia operation effectively resets the state of the SW CSRNG instance,
* clearing any errors that it may have encountered due to bad command syntax or
* entropy source failures.
*
* @return Operation status in `status_t` format.
*/
OT_WARN_UNUSED_RESULT
status_t entropy_csrng_uninstantiate(void);

#ifdef __cplusplus
}
#endif

#endif // OPENTITAN_SW_DEVICE_LIB_CRYPTO_DRIVERS_ENTROPY_H_
Loading

0 comments on commit e0468a5

Please sign in to comment.