drivers/at86rf2xx: SPI AES security module
This commit is contained in:
parent
02a714e06f
commit
1fca10c486
@ -1 +1,7 @@
|
|||||||
|
# exclude submodule sources from *.c wildcard source selection
|
||||||
|
SRC := $(filter-out aes_spi.c,$(wildcard *.c))
|
||||||
|
|
||||||
|
# enable submodules
|
||||||
|
SUBMODULES := 1
|
||||||
|
|
||||||
include $(RIOTBASE)/Makefile.base
|
include $(RIOTBASE)/Makefile.base
|
||||||
|
|||||||
350
drivers/at86rf2xx/aes_spi.c
Normal file
350
drivers/at86rf2xx/aes_spi.c
Normal file
@ -0,0 +1,350 @@
|
|||||||
|
/* Copyright (C) 2020 Otto-von-Guericke-Universität Magdeburg
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup drivers_at86rf2xx
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Implementation of at86rf2xx SPI security module (AES)
|
||||||
|
*
|
||||||
|
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xtimer.h"
|
||||||
|
#include "periph/spi.h"
|
||||||
|
#include "at86rf2xx_aes.h"
|
||||||
|
|
||||||
|
#define ENABLE_DEBUG (0)
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
#define AES_DEBUG(...) DEBUG("[at86rf2xx_aes_spi]: "__VA_ARGS__)
|
||||||
|
|
||||||
|
#define AT86RF2XX_CMD_SRAM_READ (0b00000000)
|
||||||
|
#define AT86RF2XX_CMD_SRAM_WRITE (0b01000000)
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void at86rf2xx_spi_get_bus(const at86rf2xx_t *dev)
|
||||||
|
{
|
||||||
|
spi_acquire(dev->params.spi, dev->params.cs_pin, SPI_MODE_0, dev->params.spi_clk);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void at86rf2xx_spi_release_bus(const at86rf2xx_t *dev)
|
||||||
|
{
|
||||||
|
spi_release(dev->params.spi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
uint8_t _aes_status(at86rf2xx_t *dev)
|
||||||
|
{
|
||||||
|
spi_transfer_byte(dev->params.spi, dev->params.cs_pin, true,
|
||||||
|
AT86RF2XX_CMD_SRAM_READ);
|
||||||
|
spi_transfer_byte(dev->params.spi, dev->params.cs_pin, true,
|
||||||
|
AT86RF2XX_REG__AES_STATUS);
|
||||||
|
return spi_transfer_byte(dev->params.spi, dev->params.cs_pin, false, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void _aes_wait_for_result(at86rf2xx_t *dev)
|
||||||
|
{
|
||||||
|
xtimer_usleep(AT86RF2XX_AES_DELAY_US);
|
||||||
|
uint8_t status = _aes_status(dev);
|
||||||
|
/*
|
||||||
|
If this assert fires, there probably is an implementation error.
|
||||||
|
The error bit is set before the transceiver has processed a data block.
|
||||||
|
There are two cases:
|
||||||
|
1. The delay between initiating an AES operation and sending the next cfg
|
||||||
|
to AT86RF2XX_REG__AES_CTRL was too short. Meaning the transceiver
|
||||||
|
did not have enough time to process the current block.
|
||||||
|
2. Less then 16 bytes of data have been sent to the transceiver.
|
||||||
|
|
||||||
|
Both should not occur in the code.
|
||||||
|
*/
|
||||||
|
assert(!(status & AT86RF2XX_AES_STATUS_MASK__AES_ER));
|
||||||
|
while (!(status & AT86RF2XX_AES_STATUS_MASK__AES_DONE)) {
|
||||||
|
AES_DEBUG("status: %02x\n", status);
|
||||||
|
status = _aes_status(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void _aes_open_read(at86rf2xx_t *dev, uint8_t addr)
|
||||||
|
{
|
||||||
|
spi_transfer_byte(dev->params.spi, dev->params.cs_pin, true,
|
||||||
|
AT86RF2XX_CMD_SRAM_READ);
|
||||||
|
spi_transfer_byte(dev->params.spi, dev->params.cs_pin, true,
|
||||||
|
addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void _aes_open_write(at86rf2xx_t *dev, uint8_t addr)
|
||||||
|
{
|
||||||
|
spi_transfer_byte(dev->params.spi, dev->params.cs_pin, true,
|
||||||
|
AT86RF2XX_CMD_SRAM_WRITE);
|
||||||
|
spi_transfer_byte(dev->params.spi, dev->params.cs_pin, true,
|
||||||
|
addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void _aes_transfer_bytes(at86rf2xx_t *dev, bool cont, const void* out,
|
||||||
|
void* in, size_t len)
|
||||||
|
{
|
||||||
|
spi_transfer_bytes(dev->params.spi, dev->params.cs_pin, cont, out,
|
||||||
|
in, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void _aes_save_key(at86rf2xx_t *dev, uint8_t cfg, uint8_t key[AT86RF2XX_AES_BLOCK_SIZE])
|
||||||
|
{
|
||||||
|
_aes_open_write(dev, AT86RF2XX_REG__AES_CTRL);
|
||||||
|
_aes_transfer_bytes(dev, false, &cfg, NULL, sizeof(cfg));
|
||||||
|
_aes_open_read(dev, AT86RF2XX_REG__AES_KEY_START);
|
||||||
|
_aes_transfer_bytes(dev, false, NULL, key, AT86RF2XX_AES_KEY_LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void _aes_transfer_block(at86rf2xx_t *dev, uint8_t cfg, uint8_t mirror,
|
||||||
|
const aes_block_t src, aes_block_t dst)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
cfg:
|
||||||
|
value which tells the AES engine what kind of data is coming in
|
||||||
|
mirror:
|
||||||
|
must be the same value as cfg but depending on whether the bit
|
||||||
|
AT86RF2XX_AES_CTRL_MIRROR_MASK__AES_REQUEST is set, the transceiver
|
||||||
|
will process the incoming block, or not
|
||||||
|
src:
|
||||||
|
current data block of 16 bytes to be sent to the AES engine
|
||||||
|
dst:
|
||||||
|
if not NULL, dst stores the processed data block of the
|
||||||
|
block that has been sent to the AES engine most recently
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* access SRAM register AES_CTRL for writing */
|
||||||
|
_aes_open_write(dev, AT86RF2XX_REG__AES_CTRL);
|
||||||
|
/* MOSI: send configuration to the AES_CTRL register */
|
||||||
|
_aes_transfer_bytes(dev, true, &cfg, NULL, sizeof(cfg));
|
||||||
|
/* MOSI: send first byte of the current block (block_i) */
|
||||||
|
_aes_transfer_bytes(dev, true, src, NULL, 1);
|
||||||
|
/* MOSI: send the last 15 bytes of block_i */
|
||||||
|
/* MISO: get the first 15 bytes of the most recently processed block (block_i-1) */
|
||||||
|
_aes_transfer_bytes(dev, true, src + 1, dst, AT86RF2XX_AES_BLOCK_SIZE - 1);
|
||||||
|
/* MOSI: send the mirrored cfg value and initiate the processing of block_i (or not) */
|
||||||
|
/* MISO: get the last byte of block_i-1 */
|
||||||
|
_aes_transfer_bytes(dev, false, &mirror,
|
||||||
|
dst ? dst + AT86RF2XX_AES_BLOCK_SIZE - 1 : NULL, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void at86rf2xx_aes_key_read_encrypt(at86rf2xx_t *dev,
|
||||||
|
uint8_t key[AT86RF2XX_AES_KEY_LENGTH])
|
||||||
|
{
|
||||||
|
uint8_t cfg = AT86RF2XX_AES_CTRL_AES_MODE__KEY |
|
||||||
|
AT86RF2XX_AES_CTRL_AES_DIR__ENC;
|
||||||
|
at86rf2xx_spi_get_bus(dev);
|
||||||
|
_aes_save_key(dev, cfg, key);
|
||||||
|
at86rf2xx_spi_release_bus(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
void at86rf2xx_aes_key_write_encrypt(at86rf2xx_t *dev,
|
||||||
|
const uint8_t key[AT86RF2XX_AES_KEY_LENGTH])
|
||||||
|
{
|
||||||
|
uint8_t cfg = AT86RF2XX_AES_CTRL_AES_MODE__KEY |
|
||||||
|
AT86RF2XX_AES_CTRL_AES_DIR__ENC;
|
||||||
|
at86rf2xx_spi_get_bus(dev);
|
||||||
|
_aes_open_write(dev, AT86RF2XX_REG__AES_CTRL);
|
||||||
|
_aes_transfer_bytes(dev, true, &cfg, NULL, sizeof(cfg));
|
||||||
|
_aes_transfer_bytes(dev, false, key, NULL, AT86RF2XX_AES_KEY_LENGTH);
|
||||||
|
at86rf2xx_spi_release_bus(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
void at86rf2xx_aes_key_read_decrypt(at86rf2xx_t *dev,
|
||||||
|
uint8_t key[AT86RF2XX_AES_KEY_LENGTH])
|
||||||
|
{
|
||||||
|
uint8_t cfg = AT86RF2XX_AES_CTRL_AES_MODE__KEY |
|
||||||
|
AT86RF2XX_AES_CTRL_AES_DIR__DEC;
|
||||||
|
at86rf2xx_spi_get_bus(dev);
|
||||||
|
_aes_save_key(dev, cfg, key);
|
||||||
|
at86rf2xx_spi_release_bus(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
void at86rf2xx_aes_key_write_decrypt(at86rf2xx_t *dev,
|
||||||
|
const uint8_t key[AT86RF2XX_AES_KEY_LENGTH])
|
||||||
|
{
|
||||||
|
uint8_t cfg = AT86RF2XX_AES_CTRL_AES_MODE__KEY |
|
||||||
|
AT86RF2XX_AES_CTRL_AES_DIR__DEC;
|
||||||
|
at86rf2xx_spi_get_bus(dev);
|
||||||
|
_aes_open_write(dev, AT86RF2XX_REG__AES_CTRL);
|
||||||
|
_aes_transfer_bytes(dev, true, &cfg, NULL, sizeof(cfg));
|
||||||
|
_aes_transfer_bytes(dev, false, key, NULL, AT86RF2XX_AES_KEY_LENGTH);
|
||||||
|
at86rf2xx_spi_release_bus(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
void at86rf2xx_aes_ecb_encrypt(at86rf2xx_t *dev,
|
||||||
|
aes_block_t *cipher,
|
||||||
|
uint8_t key[AT86RF2XX_AES_BLOCK_SIZE],
|
||||||
|
const aes_block_t *plain,
|
||||||
|
uint8_t nblocks)
|
||||||
|
{
|
||||||
|
if (!nblocks) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint8_t cfg = AT86RF2XX_AES_CTRL_AES_MODE__ECB |
|
||||||
|
AT86RF2XX_AES_CTRL_AES_DIR__ENC;
|
||||||
|
uint8_t mirror = cfg | AT86RF2XX_AES_CTRL_MIRROR_MASK__AES_REQUEST;
|
||||||
|
at86rf2xx_spi_get_bus(dev);
|
||||||
|
_aes_transfer_block(dev, cfg, mirror, plain[0], NULL);
|
||||||
|
_aes_wait_for_result(dev);
|
||||||
|
if (key) {
|
||||||
|
cfg = AT86RF2XX_AES_CTRL_AES_MODE__KEY |
|
||||||
|
AT86RF2XX_AES_CTRL_AES_DIR__DEC;
|
||||||
|
_aes_save_key(dev, cfg, key);
|
||||||
|
}
|
||||||
|
cfg = AT86RF2XX_AES_CTRL_AES_MODE__ECB |
|
||||||
|
AT86RF2XX_AES_CTRL_AES_DIR__ENC;
|
||||||
|
for (unsigned i = 1; i < nblocks; i++) {
|
||||||
|
_aes_transfer_block(dev, cfg, mirror, plain[i],
|
||||||
|
cipher ? cipher[i - 1] : NULL);
|
||||||
|
_aes_wait_for_result(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send dummy bytes to get the last block of cipher text */
|
||||||
|
mirror &= ~AT86RF2XX_AES_CTRL_MIRROR_MASK__AES_REQUEST;
|
||||||
|
_aes_transfer_block(dev, cfg, mirror, plain[0],
|
||||||
|
cipher ? cipher[nblocks - 1] : NULL);
|
||||||
|
at86rf2xx_spi_release_bus(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
void at86rf2xx_aes_ecb_decrypt(at86rf2xx_t *dev,
|
||||||
|
aes_block_t *plain,
|
||||||
|
uint8_t key[AT86RF2XX_AES_BLOCK_SIZE],
|
||||||
|
const aes_block_t *cipher,
|
||||||
|
uint8_t nblocks)
|
||||||
|
{
|
||||||
|
if (!nblocks) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint8_t cfg = AT86RF2XX_AES_CTRL_AES_MODE__ECB |
|
||||||
|
AT86RF2XX_AES_CTRL_AES_DIR__DEC;
|
||||||
|
uint8_t mirror = cfg | AT86RF2XX_AES_CTRL_MIRROR_MASK__AES_REQUEST;
|
||||||
|
at86rf2xx_spi_get_bus(dev);
|
||||||
|
_aes_transfer_block(dev, cfg, mirror, cipher[0], NULL);
|
||||||
|
_aes_wait_for_result(dev);
|
||||||
|
if (key) {
|
||||||
|
cfg = AT86RF2XX_AES_CTRL_AES_MODE__KEY |
|
||||||
|
AT86RF2XX_AES_CTRL_AES_DIR__ENC;
|
||||||
|
_aes_save_key(dev, cfg, key);
|
||||||
|
}
|
||||||
|
cfg = AT86RF2XX_AES_CTRL_AES_MODE__ECB |
|
||||||
|
AT86RF2XX_AES_CTRL_AES_DIR__DEC;
|
||||||
|
for (unsigned i = 1; i < nblocks; i++) {
|
||||||
|
_aes_transfer_block(dev, cfg, mirror, cipher[i],
|
||||||
|
plain ? plain[i - 1] : NULL);
|
||||||
|
_aes_wait_for_result(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send dummy bytes to get the last block of plain text */
|
||||||
|
mirror &= ~AT86RF2XX_AES_CTRL_MIRROR_MASK__AES_REQUEST;
|
||||||
|
_aes_transfer_block(dev, cfg, mirror, cipher[0],
|
||||||
|
plain ? plain[nblocks - 1] : NULL);
|
||||||
|
at86rf2xx_spi_release_bus(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
void at86rf2xx_aes_cbc_encrypt(at86rf2xx_t *dev,
|
||||||
|
aes_block_t *cipher,
|
||||||
|
uint8_t key[AT86RF2XX_AES_BLOCK_SIZE],
|
||||||
|
uint8_t iv[AT86RF2XX_AES_BLOCK_SIZE],
|
||||||
|
const aes_block_t *plain,
|
||||||
|
uint8_t nblocks)
|
||||||
|
{
|
||||||
|
if (!nblocks) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint8_t cfg = AT86RF2XX_AES_CTRL_AES_MODE__ECB |
|
||||||
|
AT86RF2XX_AES_CTRL_AES_DIR__ENC;
|
||||||
|
uint8_t mirror = cfg | AT86RF2XX_AES_CTRL_MIRROR_AES_REQUEST__START;
|
||||||
|
/* The first block has to be ECB encrypted because there is no
|
||||||
|
cipher result to be XOR´ed from the last round.
|
||||||
|
Instead an "initial vector" is XOR´ed to the first block
|
||||||
|
of plain text. */
|
||||||
|
uint8_t first[AT86RF2XX_AES_BLOCK_SIZE];
|
||||||
|
for (unsigned i = 0; i < AT86RF2XX_AES_BLOCK_SIZE; i++) {
|
||||||
|
first[i] = plain[0][i] ^ iv[i];
|
||||||
|
}
|
||||||
|
at86rf2xx_spi_get_bus(dev);
|
||||||
|
_aes_transfer_block(dev, cfg, mirror, first, NULL);
|
||||||
|
_aes_wait_for_result(dev);
|
||||||
|
if (key) {
|
||||||
|
cfg = AT86RF2XX_AES_CTRL_AES_MODE__KEY |
|
||||||
|
AT86RF2XX_AES_CTRL_AES_DIR__DEC;
|
||||||
|
_aes_save_key(dev, cfg, key);
|
||||||
|
}
|
||||||
|
cfg = AT86RF2XX_AES_CTRL_AES_MODE__CBC |
|
||||||
|
AT86RF2XX_AES_CTRL_AES_DIR__ENC;
|
||||||
|
mirror = cfg | AT86RF2XX_AES_CTRL_MIRROR_AES_REQUEST__START;
|
||||||
|
for (unsigned i = 1; i < nblocks; i++) {
|
||||||
|
_aes_transfer_block(dev, cfg, mirror, plain[i],
|
||||||
|
cipher ? cipher[i - 1] : NULL);
|
||||||
|
_aes_wait_for_result(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send dummy bytes to get the last block of cipher text */
|
||||||
|
uint8_t *mac = cipher ? cipher[nblocks - 1] : iv;
|
||||||
|
mirror &= ~AT86RF2XX_AES_CTRL_MIRROR_MASK__AES_REQUEST;
|
||||||
|
_aes_transfer_block(dev, cfg, mirror, plain[0], mac);
|
||||||
|
at86rf2xx_spi_release_bus(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
void at86rf2xx_aes_cbc_decrypt(at86rf2xx_t *dev,
|
||||||
|
aes_block_t *plain,
|
||||||
|
uint8_t key[AT86RF2XX_AES_BLOCK_SIZE],
|
||||||
|
uint8_t iv[AT86RF2XX_AES_BLOCK_SIZE],
|
||||||
|
const aes_block_t *cipher,
|
||||||
|
uint8_t nblocks)
|
||||||
|
{
|
||||||
|
if (!nblocks) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint8_t cfg = AT86RF2XX_AES_CTRL_AES_MODE__ECB |
|
||||||
|
AT86RF2XX_AES_CTRL_AES_DIR__DEC;
|
||||||
|
uint8_t mirror = cfg | AT86RF2XX_AES_CTRL_MIRROR_AES_REQUEST__START;
|
||||||
|
at86rf2xx_spi_get_bus(dev);
|
||||||
|
_aes_transfer_block(dev, cfg, mirror, cipher[0], NULL);
|
||||||
|
_aes_wait_for_result(dev);
|
||||||
|
if (key) {
|
||||||
|
cfg = AT86RF2XX_AES_CTRL_AES_MODE__KEY |
|
||||||
|
AT86RF2XX_AES_CTRL_AES_DIR__ENC;
|
||||||
|
_aes_save_key(dev, cfg, key);
|
||||||
|
}
|
||||||
|
const uint8_t *xor = iv;
|
||||||
|
cfg = AT86RF2XX_AES_CTRL_AES_MODE__ECB |
|
||||||
|
AT86RF2XX_AES_CTRL_AES_DIR__DEC;
|
||||||
|
for (unsigned i = 1; i < nblocks; i++) {
|
||||||
|
_aes_transfer_block(dev, cfg, mirror, cipher[i],
|
||||||
|
plain ? plain[i - 1] : NULL);
|
||||||
|
_aes_wait_for_result(dev);
|
||||||
|
if (plain) {
|
||||||
|
for (unsigned j = 0; j < AT86RF2XX_AES_BLOCK_SIZE; j++) {
|
||||||
|
plain[i - 1][j] ^= xor[j];
|
||||||
|
}
|
||||||
|
xor = cipher[i - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send dummy bytes to get the last block of plain text */
|
||||||
|
uint8_t *mac = plain ? plain[nblocks - 1] : iv;
|
||||||
|
mirror &= ~AT86RF2XX_AES_CTRL_MIRROR_MASK__AES_REQUEST;
|
||||||
|
_aes_transfer_block(dev, cfg, mirror, cipher[0], mac);
|
||||||
|
if (plain) {
|
||||||
|
for (unsigned j = 0; j < AT86RF2XX_AES_BLOCK_SIZE; j++) {
|
||||||
|
plain[nblocks - 1][j] ^= xor[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
at86rf2xx_spi_release_bus(dev);
|
||||||
|
}
|
||||||
242
drivers/at86rf2xx/include/at86rf2xx_aes.h
Normal file
242
drivers/at86rf2xx/include/at86rf2xx_aes.h
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Otto-von-Guericke-Universität Magdeburg
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||||
|
* Public License v2.1. See the file LICENSE in the top level directory for more
|
||||||
|
* details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup drivers_at86rf2xx
|
||||||
|
*
|
||||||
|
* The extended feature set of at86rf2xx transceivers comprises a
|
||||||
|
* hardware implementation of AES. There are two supported block
|
||||||
|
* cipher modes, ECB and CBC.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Interface of the at86rf2xx security module (AES)
|
||||||
|
*
|
||||||
|
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
|
||||||
|
*/
|
||||||
|
#ifndef AT86RF2XX_AES_H
|
||||||
|
#define AT86RF2XX_AES_H
|
||||||
|
|
||||||
|
#include "at86rf2xx.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AES key length in bits
|
||||||
|
*/
|
||||||
|
#define AT86RF2XX_AES_KEY_BITS (128U)
|
||||||
|
/**
|
||||||
|
* @brief AES key length in bytes
|
||||||
|
*/
|
||||||
|
#define AT86RF2XX_AES_KEY_LENGTH ((AT86RF2XX_AES_KEY_BITS) / 8)
|
||||||
|
/**
|
||||||
|
* @brief AES block size in bytes
|
||||||
|
*/
|
||||||
|
#define AT86RF2XX_AES_BLOCK_SIZE ((AT86RF2XX_AES_KEY_BITS) / 8)
|
||||||
|
/**
|
||||||
|
* @brief Time to complete the AES algorithm in us
|
||||||
|
*/
|
||||||
|
#define AT86RF2XX_AES_DELAY_US (24)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name AES rigister addresses
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define AT86RF2XX_REG__AES_STATUS (0x82)
|
||||||
|
#define AT86RF2XX_REG__AES_CTRL (0x83)
|
||||||
|
#define AT86RF2XX_REG__AES_KEY_START (0x84)
|
||||||
|
#define AT86RF2XX_REG__AES_KEY_END (0x93)
|
||||||
|
#define AT86RF2XX_REG__AES_DATA_START (0x84)
|
||||||
|
#define AT86RF2XX_REG__AES_DATA_END (0x93)
|
||||||
|
#define AT86RF2XX_REG__AES_CTRL_MIRROR (0x94)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Layout of register AES_STATUS
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define AT86RF2XX_AES_STATUS_MASK__AES_ER (0x80)
|
||||||
|
#define AT86RF2XX_AES_STATUS_MASK__AES_DONE (0x01)
|
||||||
|
|
||||||
|
#define AT86RF2XX_AES_STATUS_AES_ER__NO_ERROR (0x00)
|
||||||
|
#define AT86RF2XX_AES_STATUS_AES_ER__ERROR (0x80)
|
||||||
|
|
||||||
|
#define AT86RF2XX_AES_STATUS_AES_DONE__NOT_DONE (0x00)
|
||||||
|
#define AT86RF2XX_AES_STATUS_AES_DONE__DONE (0x01)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Layout of register AES_CTRL
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define AT86RF2XX_AES_CTRL_MASK__AES_REQUEST (0x80)
|
||||||
|
#define AT86RF2XX_AES_CTRL_MASK__AES_MODE (0x70)
|
||||||
|
#define AT86RF2XX_AES_CTRL_MASK__AES_DIR (0x08)
|
||||||
|
|
||||||
|
#define AT86RF2XX_AES_CTRL_AES_REQUEST__IDLE (0x00)
|
||||||
|
#define AT86RF2XX_AES_CTRL_AES_REQUEST__START (0x80)
|
||||||
|
|
||||||
|
#define AT86RF2XX_AES_CTRL_AES_MODE__ECB (0x00)
|
||||||
|
#define AT86RF2XX_AES_CTRL_AES_MODE__KEY (0x10)
|
||||||
|
#define AT86RF2XX_AES_CTRL_AES_MODE__CBC (0x20)
|
||||||
|
|
||||||
|
#define AT86RF2XX_AES_CTRL_AES_DIR__ENC (0x00)
|
||||||
|
#define AT86RF2XX_AES_CTRL_AES_DIR__DEC (0x08)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Layout of register AES_CTRL_MIRROR
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define AT86RF2XX_AES_CTRL_MIRROR_MASK__AES_REQUEST (0x80)
|
||||||
|
#define AT86RF2XX_AES_CTRL_MIRROR_MASK__AES_MODE (0x70)
|
||||||
|
#define AT86RF2XX_AES_CTRL_MIRROR_MASK__AES_DIR (0x08)
|
||||||
|
|
||||||
|
#define AT86RF2XX_AES_CTRL_MIRROR_AES_REQUEST__IDLE (0x00)
|
||||||
|
#define AT86RF2XX_AES_CTRL_MIRROR_AES_REQUEST__START (0x80)
|
||||||
|
|
||||||
|
#define AT86RF2XX_AES_CTRL_MIRROR_AES_MODE__ECB (0x00)
|
||||||
|
#define AT86RF2XX_AES_CTRL_MIRROR_AES_MODE__KEY (0x10)
|
||||||
|
#define AT86RF2XX_AES_CTRL_MIRROR_AES_MODE__CBC (0x20)
|
||||||
|
|
||||||
|
#define AT86RF2XX_AES_CTRL_MIRROR_AES_DIR__ENC (0x00)
|
||||||
|
#define AT86RF2XX_AES_CTRL_MIRROR_AES_DIR__DEC (0x08)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief An AES block
|
||||||
|
*
|
||||||
|
* AES works on blocks of 16 bytes
|
||||||
|
*/
|
||||||
|
typedef uint8_t aes_block_t[AT86RF2XX_AES_BLOCK_SIZE];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read the AES key used for encryption
|
||||||
|
*
|
||||||
|
* @param[in] dev Device
|
||||||
|
* @param[out] key Buffer to store the key
|
||||||
|
*/
|
||||||
|
void at86rf2xx_aes_key_read_encrypt(at86rf2xx_t *dev,
|
||||||
|
uint8_t key[AT86RF2XX_AES_KEY_LENGTH]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write the AES key used for encryption
|
||||||
|
*
|
||||||
|
* It is important to write the encryption key, before encryption is done
|
||||||
|
*
|
||||||
|
* @param[in] dev Device
|
||||||
|
* @param[in] key Buffer which stores the key
|
||||||
|
*/
|
||||||
|
void at86rf2xx_aes_key_write_encrypt(at86rf2xx_t *dev,
|
||||||
|
const uint8_t key[AT86RF2XX_AES_KEY_LENGTH]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read the AES key used for decryption
|
||||||
|
*
|
||||||
|
* @param[in] dev Device
|
||||||
|
* @param[out] key Buffer to store the key
|
||||||
|
*/
|
||||||
|
void at86rf2xx_aes_key_read_decrypt(at86rf2xx_t *dev,
|
||||||
|
uint8_t key[AT86RF2XX_AES_KEY_LENGTH]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write the AES key used for decryption
|
||||||
|
*
|
||||||
|
* It is important to write the decryption key, before decryption is done
|
||||||
|
*
|
||||||
|
* @param[in] dev Device
|
||||||
|
* @param[in] key Buffer which stores the key
|
||||||
|
*/
|
||||||
|
void at86rf2xx_aes_key_write_decrypt(at86rf2xx_t *dev,
|
||||||
|
const uint8_t key[AT86RF2XX_AES_KEY_LENGTH]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Perform AES algorithm and encrypt data blocks
|
||||||
|
* in @p plain to cipher data blocks, using ECB mode
|
||||||
|
*
|
||||||
|
* @note The encryption key must have been written before.
|
||||||
|
*
|
||||||
|
* @param[in] dev Device
|
||||||
|
* @param[out] cipher If not NULL, cipher data blocks
|
||||||
|
* @param[out] key If not NULL, last round encryption key is stored
|
||||||
|
* @param[in] plain Plain data blocks
|
||||||
|
* @param[in] nblocks Number of blocks
|
||||||
|
*/
|
||||||
|
void at86rf2xx_aes_ecb_encrypt(at86rf2xx_t *dev,
|
||||||
|
aes_block_t *cipher,
|
||||||
|
uint8_t key[AT86RF2XX_AES_BLOCK_SIZE],
|
||||||
|
const aes_block_t *plain,
|
||||||
|
uint8_t nblocks);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Perform AES algorithm and decrypt data blocks
|
||||||
|
* in @p cipher to plain data blocks, using ECB mode
|
||||||
|
*
|
||||||
|
* @note The decryption key must have been written before.
|
||||||
|
*
|
||||||
|
* @param[in] dev Device
|
||||||
|
* @param[out] plain If not NULL, plain data blocks
|
||||||
|
* @param[out] key If not NULL, last round decryption key is stored
|
||||||
|
* @param[in] cipher Cipher data blocks
|
||||||
|
* @param[in] nblocks Number of blocks
|
||||||
|
*/
|
||||||
|
void at86rf2xx_aes_ecb_decrypt(at86rf2xx_t *dev,
|
||||||
|
aes_block_t *plain,
|
||||||
|
uint8_t key[AT86RF2XX_AES_BLOCK_SIZE],
|
||||||
|
const aes_block_t *cipher,
|
||||||
|
uint8_t nblocks);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Perform AES algorithm and encrypt data blocks
|
||||||
|
* in @p plain to cipher data blocks, using CBC mode
|
||||||
|
*
|
||||||
|
* @note The encryption key must have been written before.
|
||||||
|
*
|
||||||
|
* @param[in] dev Device
|
||||||
|
* @param[out] cipher If not NULL, cipher blocks
|
||||||
|
* @param[out] key If not NULL, last round encryption key is stored
|
||||||
|
* @param[in,out] iv in: initial vector, out: last cipher block if cipher is NULL
|
||||||
|
* @param[in] plain Plain data blocks
|
||||||
|
* @param[in] nblocks Number of blocks
|
||||||
|
*/
|
||||||
|
void at86rf2xx_aes_cbc_encrypt(at86rf2xx_t *dev,
|
||||||
|
aes_block_t *cipher,
|
||||||
|
uint8_t key[AT86RF2XX_AES_BLOCK_SIZE],
|
||||||
|
uint8_t iv[AT86RF2XX_AES_BLOCK_SIZE],
|
||||||
|
const aes_block_t *plain,
|
||||||
|
uint8_t nblocks);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Perform AES algorithm and decrypt data blocks
|
||||||
|
* in @p cipher to plain data blocks, using CBC mode
|
||||||
|
*
|
||||||
|
* @note The decryption key must have been written before.
|
||||||
|
*
|
||||||
|
* @param[in] dev Device
|
||||||
|
* @param[out] plain If not NUll, plain data blocks
|
||||||
|
* @param[out] key If not NULL, last round decryption key is stored
|
||||||
|
* @param[in,out] iv in: initial vector, out: last plain block if plain is NULL
|
||||||
|
* @param[in] cipher Cipher data blocks
|
||||||
|
* @param[in] nblocks Number of blocks
|
||||||
|
*/
|
||||||
|
void at86rf2xx_aes_cbc_decrypt(at86rf2xx_t *dev,
|
||||||
|
aes_block_t *plain,
|
||||||
|
uint8_t key[AT86RF2XX_AES_BLOCK_SIZE],
|
||||||
|
uint8_t iv[AT86RF2XX_AES_BLOCK_SIZE],
|
||||||
|
const aes_block_t *cipher,
|
||||||
|
uint8_t nblocks);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* AT86RF2XX_AES_H */
|
||||||
|
/** @} */
|
||||||
@ -132,6 +132,7 @@ PSEUDOMODULES += at86rf23%
|
|||||||
PSEUDOMODULES += at86rf21%
|
PSEUDOMODULES += at86rf21%
|
||||||
PSEUDOMODULES += at86rfa1
|
PSEUDOMODULES += at86rfa1
|
||||||
PSEUDOMODULES += at86rfr2
|
PSEUDOMODULES += at86rfr2
|
||||||
|
PSEUDOMODULES += at86rf2xx_aes_spi
|
||||||
NO_PSEUDOMODULES += at86rf215
|
NO_PSEUDOMODULES += at86rf215
|
||||||
|
|
||||||
# include variants of the BME680 drivers as pseudo modules
|
# include variants of the BME680 drivers as pseudo modules
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user