blob: 59c51e509edd1563a762577b1c243899f6aef7fe [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/aes.h"
#include "aes_regs.h" // Generated.
#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
#define AES0_BASE_ADDR TOP_EARLGREY_AES_BASE_ADDR
#define AES_NUM_REGS_KEY 8
#define AES_NUM_REGS_IV 4
#define AES_NUM_REGS_DATA 4
#define REG32(add) *((volatile uint32_t *)(add))
void aes_init(aes_cfg_t aes_cfg) {
uint32_t cfg_val =
(aes_cfg.operation << AES_CTRL_SHADOWED_OPERATION_BIT) |
((aes_cfg.mode & AES_CTRL_SHADOWED_MODE_MASK)
<< AES_CTRL_SHADOWED_MODE_OFFSET) |
((aes_cfg.key_len & AES_CTRL_SHADOWED_KEY_LEN_MASK)
<< AES_CTRL_SHADOWED_KEY_LEN_OFFSET) |
(aes_cfg.manual_operation << AES_CTRL_SHADOWED_MANUAL_OPERATION_BIT);
REG32(AES0_BASE_ADDR + AES_CTRL_SHADOWED_REG_OFFSET) = cfg_val;
REG32(AES0_BASE_ADDR + AES_CTRL_SHADOWED_REG_OFFSET) = cfg_val;
};
void aes_key_put(const void *key_share0, const void *key_share1,
aes_key_len_t key_len) {
// Determine how many key registers to use.
size_t num_regs_key_used;
if (key_len == kAes256) {
num_regs_key_used = 8;
} else if (key_len == kAes192) {
num_regs_key_used = 6;
} else {
num_regs_key_used = 4;
}
// Write the used key registers.
for (int i = 0; i < num_regs_key_used; ++i) {
REG32(AES0_BASE_ADDR + AES_KEY_SHARE0_0_REG_OFFSET + i * sizeof(uint32_t)) =
((uint32_t *)key_share0)[i];
REG32(AES0_BASE_ADDR + AES_KEY_SHARE1_0_REG_OFFSET + i * sizeof(uint32_t)) =
((uint32_t *)key_share1)[i];
}
// Write the unused key registers (the AES unit requires all key registers to
// be written).
for (int i = num_regs_key_used; i < AES_NUM_REGS_KEY; ++i) {
REG32(AES0_BASE_ADDR + AES_KEY_SHARE0_0_REG_OFFSET + i * sizeof(uint32_t)) =
0x0;
REG32(AES0_BASE_ADDR + AES_KEY_SHARE1_0_REG_OFFSET + i * sizeof(uint32_t)) =
0x0;
}
}
void aes_iv_put(const void *iv) {
// Write the four initialization vector registers.
for (int i = 0; i < AES_NUM_REGS_IV; ++i) {
REG32(AES0_BASE_ADDR + AES_IV_0_REG_OFFSET + i * sizeof(uint32_t)) =
((uint32_t *)iv)[i];
}
}
void aes_data_put_wait(const void *data) {
// Wait for AES unit to be ready for new input data.
while (!aes_data_ready()) {
}
// Provide the input data.
aes_data_put(data);
}
void aes_data_put(const void *data) {
// Write the four input data registers.
for (int i = 0; i < AES_NUM_REGS_DATA; ++i) {
REG32(AES0_BASE_ADDR + AES_DATA_IN_0_REG_OFFSET + i * sizeof(uint32_t)) =
((uint32_t *)data)[i];
}
}
void aes_data_get_wait(void *data) {
// Wait for AES unit to have valid output data.
while (!aes_data_valid()) {
}
// Get the data.
aes_data_get(data);
}
void aes_data_get(void *data) {
// Read the four output data registers.
for (int i = 0; i < AES_NUM_REGS_DATA; ++i) {
((uint32_t *)data)[i] = REG32(AES0_BASE_ADDR + AES_DATA_OUT_0_REG_OFFSET +
i * sizeof(uint32_t));
}
}
bool aes_data_ready(void) {
return (REG32(AES0_BASE_ADDR + AES_STATUS_REG_OFFSET) &
(0x1u << AES_STATUS_INPUT_READY_BIT));
}
bool aes_data_valid(void) {
return (REG32(AES0_BASE_ADDR + AES_STATUS_REG_OFFSET) &
(0x1u << AES_STATUS_OUTPUT_VALID_BIT));
}
bool aes_idle(void) {
return (REG32(AES0_BASE_ADDR + AES_STATUS_REG_OFFSET) &
(0x1u << AES_STATUS_IDLE_BIT));
}
void aes_manual_trigger(void) {
REG32(AES0_BASE_ADDR + AES_TRIGGER_REG_OFFSET) = 0x1u
<< AES_TRIGGER_START_BIT;
}
void aes_clear(void) {
// Wait for AES unit to be idle.
while (!aes_idle()) {
}
// Disable autostart
uint32_t cfg_val = 0x1u << AES_CTRL_SHADOWED_MANUAL_OPERATION_BIT;
REG32(AES0_BASE_ADDR + AES_CTRL_SHADOWED_REG_OFFSET) = cfg_val;
REG32(AES0_BASE_ADDR + AES_CTRL_SHADOWED_REG_OFFSET) = cfg_val;
// Clear internal key and output registers
REG32(AES0_BASE_ADDR + AES_TRIGGER_REG_OFFSET) =
(0x1u << AES_TRIGGER_KEY_CLEAR_BIT) | (0x1u << AES_TRIGGER_IV_CLEAR_BIT) |
(0x1u << AES_TRIGGER_DATA_IN_CLEAR_BIT) |
(0x1u << AES_TRIGGER_DATA_OUT_CLEAR_BIT);
// Wait for output not valid, and input ready
while (!(!aes_data_valid() && aes_data_ready())) {
}
}