blob: 9e916a8e317db405b5934ce04401e380e6ecc002 [file] [log] [blame]
// 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/dif/dif_csrng.h"
#include "gtest/gtest.h"
#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/testing/mock_mmio.h"
#include "csrng_regs.h" // Generated
namespace dif_entropy_unittest {
namespace {
class DifCsrngTest : public testing::Test, public mock_mmio::MmioTest {
protected:
const dif_csrng_params_t params_ = {.base_addr = dev().region()};
const dif_csrng_t csrng_ = {
.params = {.base_addr = dev().region()},
};
};
class InitTest : public DifCsrngTest {};
TEST_F(InitTest, BadArgs) {
EXPECT_EQ(dif_csrng_init(params_, nullptr), kDifCsrngBadArg);
}
TEST_F(InitTest, InitOk) {
dif_csrng_t csrng;
EXPECT_EQ(dif_csrng_init(params_, &csrng), kDifCsrngOk);
}
class ConfigTest : public DifCsrngTest {
protected:
/**
* Sets CTRL write register expectations.
*/
void ExpectCtrlWrite(bool bypass_aes_cipher) {
EXPECT_WRITE32(CSRNG_CTRL_REG_OFFSET,
{
{CSRNG_CTRL_ENABLE_BIT, true},
{CSRNG_CTRL_AES_CIPHER_DISABLE_BIT, bypass_aes_cipher},
{CSRNG_CTRL_FIFO_DEPTH_STS_SEL_OFFSET, 0},
});
}
dif_csrng_config_t config_ = {
.debug_config = {.bypass_aes_cipher = false},
};
};
TEST_F(ConfigTest, NullArgs) {
EXPECT_EQ(dif_csrng_configure(nullptr, {}), kDifCsrngBadArg);
}
TEST_F(ConfigTest, ConfigOk) {
config_.debug_config.bypass_aes_cipher = false;
ExpectCtrlWrite(config_.debug_config.bypass_aes_cipher);
EXPECT_EQ(dif_csrng_configure(&csrng_, config_), kDifCsrngOk);
}
TEST_F(ConfigTest, ConfigAesBypassOk) {
config_.debug_config.bypass_aes_cipher = true;
ExpectCtrlWrite(config_.debug_config.bypass_aes_cipher);
EXPECT_EQ(dif_csrng_configure(&csrng_, config_), kDifCsrngOk);
}
class GetCmdInterfaceStatusTest : public DifCsrngTest {};
TEST_F(GetCmdInterfaceStatusTest, NullArgs) {
dif_csrng_cmd_status_t status;
EXPECT_EQ(dif_csrng_get_cmd_interface_status(nullptr, &status),
kDifCsrngBadArg);
EXPECT_EQ(dif_csrng_get_cmd_interface_status(&csrng_, nullptr),
kDifCsrngBadArg);
}
struct GetCmdInterfaceStatusParams {
bool cmd_ready;
bool cmd_status;
dif_csrng_cmd_status_t expected_status;
};
class GetCmdInterfaceStatusTestAllParams
: public GetCmdInterfaceStatusTest,
public testing::WithParamInterface<GetCmdInterfaceStatusParams> {};
TEST_P(GetCmdInterfaceStatusTestAllParams, ValidConfigurationMode) {
const GetCmdInterfaceStatusParams &test_param = GetParam();
dif_csrng_cmd_status_t status;
EXPECT_READ32(CSRNG_SW_CMD_STS_REG_OFFSET,
{
{CSRNG_SW_CMD_STS_CMD_RDY_BIT, test_param.cmd_ready},
{CSRNG_SW_CMD_STS_CMD_STS_BIT, test_param.cmd_status},
});
EXPECT_EQ(dif_csrng_get_cmd_interface_status(&csrng_, &status), kDifCsrngOk);
EXPECT_EQ(status, test_param.expected_status);
}
INSTANTIATE_TEST_SUITE_P(
GetCmdInterfaceStatusTestAllParams, GetCmdInterfaceStatusTestAllParams,
testing::Values(
GetCmdInterfaceStatusParams{true, false, kDifCsrngCmdStatusReady},
GetCmdInterfaceStatusParams{true, true, kDifCsrngCmdStatusError},
GetCmdInterfaceStatusParams{false, true, kDifCsrngCmdStatusError},
GetCmdInterfaceStatusParams{false, false, kDifCsrngCmdStatusBusy}));
class GetOutputStatusTest : public DifCsrngTest {};
TEST_F(GetOutputStatusTest, NullArgs) {
dif_csrng_output_status_t status;
EXPECT_EQ(dif_csrng_get_output_status(nullptr, &status), kDifCsrngBadArg);
EXPECT_EQ(dif_csrng_get_output_status(&csrng_, nullptr), kDifCsrngBadArg);
}
TEST_F(GetOutputStatusTest, ValidStatus) {
// Each option is initialized to a boolean complement of the other so
// that we can test both fields toggling in one pass.
dif_csrng_output_status_t status = {.valid_data = false, .fips_mode = true};
EXPECT_READ32(CSRNG_GENBITS_VLD_REG_OFFSET,
{
{CSRNG_GENBITS_VLD_GENBITS_VLD_BIT, true},
{CSRNG_GENBITS_VLD_GENBITS_FIPS_BIT, false},
});
EXPECT_EQ(dif_csrng_get_output_status(&csrng_, &status), kDifCsrngOk);
EXPECT_EQ(status.valid_data, true);
EXPECT_EQ(status.fips_mode, false);
}
} // namespace
} // namespace dif_entropy_unittest