From f074e8a635d4d4a7d663ce8dbe297556445e2e67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20H=C3=BC=C3=9Fler?= Date: Fri, 2 Oct 2020 19:39:43 +0200 Subject: [PATCH] drivers/at86rf2xx: Use hardware security for IEEE 802.15.4 security --- drivers/at86rf2xx/at86rf2xx.c | 87 ++++++++++++++++++++++++++++ drivers/at86rf2xx/at86rf2xx_netdev.c | 19 ++++++ 2 files changed, 106 insertions(+) diff --git a/drivers/at86rf2xx/at86rf2xx.c b/drivers/at86rf2xx/at86rf2xx.c index 9a3d84dd72..2697d07247 100644 --- a/drivers/at86rf2xx/at86rf2xx.c +++ b/drivers/at86rf2xx/at86rf2xx.c @@ -28,14 +28,91 @@ #include "luid.h" #include "byteorder.h" #include "net/ieee802154.h" +#if IS_USED(IEEE802154_SECURITY) +#include "net/ieee802154_security.h" +#endif #include "net/gnrc.h" #include "at86rf2xx_registers.h" #include "at86rf2xx_internal.h" #include "at86rf2xx_netdev.h" +#if IS_USED(MODULE_AT86RF2XX_AES_SPI) +#include "at86rf2xx_aes.h" +#endif #define ENABLE_DEBUG 0 #include "debug.h" +#if IS_USED(MODULE_AT86RF2XX_AES_SPI) && \ + IS_USED(MODULE_IEEE802154_SECURITY) +/** + * @brief Pass the 802.15.4 encryption key to the transceiver hardware + * + * @param[in] dev Abstract security device descriptor + * @param[in] key Encryption key to be used + * @param[in] key_size Size of the encryption key in bytes + */ +static void _at86rf2xx_set_key(ieee802154_sec_dev_t *dev, + const uint8_t *key, uint8_t key_size) +{ + (void)key_size; + at86rf2xx_aes_key_write_encrypt((at86rf2xx_t *)dev->ctx, key); +} + +/** + * @brief Compute CBC-MAC from IEEE 802.15.4 security context + * + * @param[in] dev Abstract security device descriptor + * @param[out] cipher Buffer to store cipher blocks + * @param[in] iv Initial vector + * @param[in] plain Input data blocks + * @param[in] nblocks Number of blocks + */ +static void _at86rf2xx_cbc(const ieee802154_sec_dev_t *dev, + uint8_t *cipher, + uint8_t *iv, + const uint8_t *plain, + uint8_t nblocks) +{ + at86rf2xx_aes_cbc_encrypt((at86rf2xx_t *)dev->ctx, + (aes_block_t *)cipher, + NULL, + iv, + (aes_block_t *)plain, + nblocks); +} + +/** + * @brief Perform ECB encryption + * + * @param[in] dev Abstract security device descriptor + * @param[out] cipher Output cipher blocks + * @param[in] plain Plain blocks + * @param[in] nblocks Number of blocks + */ +static void _at86rf2xx_ecb(const ieee802154_sec_dev_t *dev, + uint8_t *cipher, + const uint8_t *plain, + uint8_t nblocks) +{ + at86rf2xx_aes_ecb_encrypt((at86rf2xx_t *)dev->ctx, + (aes_block_t *)cipher, + NULL, + (aes_block_t *)plain, + nblocks); + +} +/** + * @brief Struct that contains IEEE 802.15.4 security operations + * which are implemented, using the transceiver´s hardware + * crypto capabilities + */ +static const ieee802154_radio_cipher_ops_t _at86rf2xx_cipher_ops = { + .set_key = _at86rf2xx_set_key, + .ecb = _at86rf2xx_ecb, + .cbc = _at86rf2xx_cbc +}; +#endif /* IS_USED(MODULE_AT86RF2XX_COMMON_AES_SPI) && \ + IS_USED(MODULE_IEEE802154_SECURITY) */ void at86rf2xx_setup(at86rf2xx_t *dev, const at86rf2xx_params_t *params, uint8_t index) { @@ -152,6 +229,16 @@ void at86rf2xx_reset(at86rf2xx_t *dev) /* clear interrupt flags */ at86rf2xx_reg_read(dev, AT86RF2XX_REG__IRQ_STATUS); +#if IS_USED(MODULE_IEEE802154_SECURITY) && \ + IS_USED(MODULE_AT86RF2XX_AES_SPI) + dev->netdev.sec_ctx.dev.cipher_ops = &_at86rf2xx_cipher_ops; + dev->netdev.sec_ctx.dev.ctx = dev; + /* All configurations of the security module, the SRAM content, + and keys are reset during DEEP_SLEEP or RESET state. */ + at86rf2xx_aes_key_write_encrypt(dev, + dev->netdev.sec_ctx.cipher.context.context); +#endif + /* State to return after receiving or transmitting */ dev->idle_state = AT86RF2XX_PHY_STATE_RX; /* go into RX state */ diff --git a/drivers/at86rf2xx/at86rf2xx_netdev.c b/drivers/at86rf2xx/at86rf2xx_netdev.c index 4efb9decb7..1def1bbc05 100644 --- a/drivers/at86rf2xx/at86rf2xx_netdev.c +++ b/drivers/at86rf2xx/at86rf2xx_netdev.c @@ -39,6 +39,9 @@ #include "at86rf2xx_netdev.h" #include "at86rf2xx_internal.h" #include "at86rf2xx_registers.h" +#if IS_USED(MODULE_AT86RF2XX_AES_SPI) +#include "at86rf2xx_aes.h" +#endif #define ENABLE_DEBUG 0 #include "debug.h" @@ -665,6 +668,22 @@ static int _set(netdev_t *netdev, netopt_t opt, const void *val, size_t len) #endif /* MODULE_NETDEV_IEEE802154_OQPSK */ +#if IS_USED(MODULE_AT86RF2XX_COMMON_AES_SPI) && \ + IS_USED(MODULE_IEEE802154_SECURITY) + case NETOPT_ENCRYPTION_KEY: + assert(len >= IEEE802154_SEC_KEY_LENGTH); + at86rf2xx_aes_key_write_encrypt(dev, val); + if (memcmp(dev->netdev.sec_ctx.cipher.context.context, val, len)) { + /* If the key changes, the frame conter can be reset to 0*/ + dev->netdev.sec_ctx.frame_counter = 0; + } + memcpy(dev->netdev.sec_ctx.cipher.context.context, val, + IEEE802154_SEC_KEY_LENGTH); + res = IEEE802154_SEC_KEY_LENGTH; + break; +#endif /* IS_USED(MODULE_AT86RF2XX_AES_SPI) && \ + IS_USED(MODULE_IEEE802154_SECURITY) */ + default: break; }