blob: bf2a22aa23a784953b49a9ba75db16089819f7f3 [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_aes.h"
#include "gtest/gtest.h"
#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/base/testing/mock_mmio.h"
extern "C" {
#include "aes_regs.h" // Generated.
} // extern "C"
namespace dif_aes_test {
namespace {
using mock_mmio::MmioTest;
using mock_mmio::MockDevice;
using testing::Test;
// Base class for the rest fixtures in this file.
class AesTest : public testing::Test, public mock_mmio::MmioTest {
public:
void setExpectedKey(const dif_aes_key_share_t &key, uint32_t key_size = 8) {
for (uint32_t i = 0; i < key_size; ++i) {
ptrdiff_t offset = AES_KEY_SHARE0_0_REG_OFFSET + (i * sizeof(uint32_t));
EXPECT_WRITE32(offset, key.share0[i]);
}
for (uint32_t i = 0; i < key_size; ++i) {
ptrdiff_t offset = AES_KEY_SHARE1_0_REG_OFFSET + (i * sizeof(uint32_t));
EXPECT_WRITE32(offset, key.share1[i]);
}
}
void setExpectedIv(const dif_aes_iv_t &iv, const uint32_t kIvSize = 4) {
for (uint32_t i = 0; i < kIvSize; ++i) {
ptrdiff_t offset = AES_IV_0_REG_OFFSET + (i * sizeof(uint32_t));
EXPECT_WRITE32(offset, iv.iv[i]);
}
}
void setExpectedConfig(uint32_t key_len, uint32_t mode, uint32_t operation) {
for (int i = 0; i < 2; i++) {
EXPECT_WRITE32(AES_CTRL_SHADOWED_REG_OFFSET,
{{AES_CTRL_SHADOWED_KEY_LEN_OFFSET, key_len},
{AES_CTRL_SHADOWED_MODE_OFFSET, mode},
{AES_CTRL_SHADOWED_OPERATION_OFFSET, operation},
{AES_CTRL_SHADOWED_MANUAL_OPERATION_BIT, false},
{AES_CTRL_SHADOWED_FORCE_ZERO_MASKS_BIT, false}});
}
}
};
// Init tests
class AesInitTest : public AesTest {};
TEST_F(AesInitTest, NullArgs) {
EXPECT_EQ(dif_aes_init(dev().region(), nullptr), kDifBadArg);
}
TEST_F(AesInitTest, Sucess) {
dif_aes_t aes;
EXPECT_EQ(dif_aes_init(dev().region(), &aes), kDifOk);
}
// Base class for the rest of the tests in this file, provides a
// `dif_aes_t` instance.
class AesTestInitialized : public AesTest {
protected:
dif_aes_t aes_;
dif_aes_transaction_t transaction = {
.operation = kDifAesOperationEncrypt,
.mode = kDifAesModeEcb,
.key_len = kDifAesKey128,
.manual_operation = kDifAesManualOperationAuto,
.masking = kDifAesMaskingInternalPrng,
};
const dif_aes_key_share_t kKey_ = {
.share0 = {0x59, 0x70, 0x33, 0x73, 0x36, 0x76, 0x39, 0x79},
.share1 = {0x4B, 0x61, 0x50, 0x64, 0x53, 0x67, 0x56, 0x6B}};
const dif_aes_iv_t kIv_ = {0x50, 0x64, 0x53, 0x67};
AesTestInitialized() {
EXPECT_EQ(dif_aes_init(dev().region(), &aes_), kDifOk);
}
};
// ECB tests
class EcbTest : public AesTestInitialized {
protected:
EcbTest() { transaction.mode = kDifAesModeEcb; }
};
TEST_F(EcbTest, start) {
EXPECT_READ32(AES_STATUS_REG_OFFSET, 1);
setExpectedConfig(AES_CTRL_SHADOWED_KEY_LEN_VALUE_AES_128,
AES_CTRL_SHADOWED_MODE_VALUE_AES_ECB,
AES_CTRL_SHADOWED_OPERATION_VALUE_AES_ENC);
setExpectedKey(kKey_, 8);
EXPECT_EQ(dif_aes_start(&aes_, &transaction, kKey_, NULL), kDifOk);
}
class CbcTest : public AesTestInitialized {
protected:
CbcTest() { transaction.mode = kDifAesModeCbc; }
};
TEST_F(CbcTest, start) {
EXPECT_READ32(AES_STATUS_REG_OFFSET, 1);
setExpectedConfig(AES_CTRL_SHADOWED_KEY_LEN_VALUE_AES_128,
AES_CTRL_SHADOWED_MODE_VALUE_AES_CBC,
AES_CTRL_SHADOWED_OPERATION_VALUE_AES_ENC);
setExpectedKey(kKey_, 8);
setExpectedIv(kIv_);
EXPECT_EQ(dif_aes_start(&aes_, &transaction, kKey_, &kIv_), kDifOk);
}
// CFB tests
class CFBTest : public AesTestInitialized {
protected:
CFBTest() { transaction.mode = kDifAesModeCfb; }
};
TEST_F(CFBTest, start) {
EXPECT_READ32(AES_STATUS_REG_OFFSET, 1);
setExpectedConfig(AES_CTRL_SHADOWED_KEY_LEN_VALUE_AES_128,
AES_CTRL_SHADOWED_MODE_VALUE_AES_CFB,
AES_CTRL_SHADOWED_OPERATION_VALUE_AES_ENC);
setExpectedKey(kKey_, 8);
setExpectedIv(kIv_);
EXPECT_EQ(dif_aes_start(&aes_, &transaction, kKey_, &kIv_), kDifOk);
}
// OFB tests
class OFBTest : public AesTestInitialized {
protected:
OFBTest() { transaction.mode = kDifAesModeOfb; }
};
TEST_F(OFBTest, start) {
EXPECT_READ32(AES_STATUS_REG_OFFSET, 1);
setExpectedConfig(AES_CTRL_SHADOWED_KEY_LEN_VALUE_AES_128,
AES_CTRL_SHADOWED_MODE_VALUE_AES_OFB,
AES_CTRL_SHADOWED_OPERATION_VALUE_AES_ENC);
setExpectedKey(kKey_, 8);
setExpectedIv(kIv_);
EXPECT_EQ(dif_aes_start(&aes_, &transaction, kKey_, &kIv_), kDifOk);
}
// CTR tests
class CTRTest : public AesTestInitialized {
protected:
CTRTest() { transaction.mode = kDifAesModeCtr; }
};
TEST_F(CTRTest, start) {
EXPECT_READ32(AES_STATUS_REG_OFFSET, 1);
setExpectedConfig(AES_CTRL_SHADOWED_KEY_LEN_VALUE_AES_128,
AES_CTRL_SHADOWED_MODE_VALUE_AES_CTR,
AES_CTRL_SHADOWED_OPERATION_VALUE_AES_ENC);
setExpectedKey(kKey_, 8);
setExpectedIv(kIv_);
EXPECT_EQ(dif_aes_start(&aes_, &transaction, kKey_, &kIv_), kDifOk);
}
// Decrypt tests
class DecryptTest : public AesTestInitialized {
protected:
DecryptTest() {
transaction.mode = kDifAesModeEcb;
transaction.operation = kDifAesOperationDecrypt;
}
};
TEST_F(DecryptTest, start) {
EXPECT_READ32(AES_STATUS_REG_OFFSET, 1);
setExpectedConfig(AES_CTRL_SHADOWED_KEY_LEN_VALUE_AES_128,
AES_CTRL_SHADOWED_MODE_VALUE_AES_ECB,
AES_CTRL_SHADOWED_OPERATION_VALUE_AES_DEC);
setExpectedKey(kKey_, 8);
EXPECT_EQ(dif_aes_start(&aes_, &transaction, kKey_, NULL), kDifOk);
}
} // namespace
} // namespace dif_aes_test