Use ESP32's hardware AES
This commit is contained in:
parent
49d0a7c284
commit
638e3d10a9
|
@ -16,6 +16,7 @@
|
|||
"${IDF_PATH}/components/soc/include",
|
||||
"${IDF_PATH}/components/soc/esp32/include",
|
||||
"${IDF_PATH}/components/tcpip_adapter/include",
|
||||
"${IDF_PATH}/components/mbedtls/mbedtls/include",
|
||||
"${workspaceRoot}/examples/provisioning/build/include",
|
||||
"${workspaceRoot}/examples/hello_world/build/include",
|
||||
"${workspaceRoot}/examples/send_recv/build/include",
|
||||
|
|
|
@ -54,7 +54,8 @@
|
|||
#define US_PER_OSTICK 16
|
||||
#define OSTICKS_PER_SEC (1000000 / US_PER_OSTICK)
|
||||
|
||||
#define USE_ORIGINAL_AES
|
||||
//#define USE_ORIGINAL_AES
|
||||
#define USE_MBEDTLS_AES
|
||||
|
||||
#if LMIC_DEBUG_LEVEL > 0 || LMIC_X_DEBUG_LEVEL > 0
|
||||
#include <stdio.h>
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* ttn-esp32 - The Things Network device library for ESP-IDF / SX127x
|
||||
*
|
||||
* Copyright (c) 2018 Manuel Bleichenbacher
|
||||
*
|
||||
* Licensed under MIT License
|
||||
* https://opensource.org/licenses/MIT
|
||||
*
|
||||
* AES encryption using ESP32's hardware AES unit.
|
||||
*******************************************************************************/
|
||||
|
||||
#include "mbedtls/aes.h"
|
||||
#include "../lmic/oslmic.h"
|
||||
|
||||
#if defined(USE_MBEDTLS_AES)
|
||||
|
||||
void lmic_aes_encrypt(u1_t *data, u1_t *key)
|
||||
{
|
||||
mbedtls_aes_context ctx;
|
||||
mbedtls_aes_init(&ctx);
|
||||
mbedtls_aes_setkey_enc(&ctx, key, 128);
|
||||
mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT, data, data);
|
||||
mbedtls_aes_free(&ctx);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,145 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Matthijs Kooijman
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to anyone
|
||||
* obtaining a copy of this document and accompanying files,
|
||||
* to do whatever they want with them without any restriction,
|
||||
* including, but not limited to, copying, modification and
|
||||
* redistribution.
|
||||
*
|
||||
* NO WARRANTY OF ANY KIND IS PROVIDED.
|
||||
*******************************************************************************/
|
||||
|
||||
/*
|
||||
* The original LMIC AES implementation integrates raw AES encryption
|
||||
* with CMAC and AES-CTR in a single piece of code. Most other AES
|
||||
* implementations (only) offer raw single block AES encryption, so this
|
||||
* file contains an implementation of CMAC and AES-CTR, and offers the
|
||||
* same API through the os_aes() function as the original AES
|
||||
* implementation. This file assumes that there is an encryption
|
||||
* function available with this signature:
|
||||
*
|
||||
* extern "C" void lmic_aes_encrypt(u1_t *data, u1_t *key);
|
||||
*
|
||||
* That takes a single 16-byte buffer and encrypts it wit the given
|
||||
* 16-byte key.
|
||||
*/
|
||||
|
||||
#include "../lmic/oslmic.h"
|
||||
|
||||
#if !defined(USE_ORIGINAL_AES)
|
||||
|
||||
// This should be defined elsewhere
|
||||
void lmic_aes_encrypt(u1_t *data, u1_t *key);
|
||||
|
||||
// global area for passing parameters (aux, key) and for storing round keys
|
||||
u4_t AESAUX[16/sizeof(u4_t)];
|
||||
u4_t AESKEY[11*16/sizeof(u4_t)];
|
||||
|
||||
// Shift the given buffer left one bit
|
||||
static void shift_left(xref2u1_t buf, u1_t len) {
|
||||
while (len--) {
|
||||
u1_t next = len ? buf[1] : 0;
|
||||
|
||||
u1_t val = (*buf << 1);
|
||||
if (next & 0x80)
|
||||
val |= 1;
|
||||
*buf++ = val;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply RFC4493 CMAC, using AESKEY as the key. If prepend_aux is true,
|
||||
// AESAUX is prepended to the message. AESAUX is used as working memory
|
||||
// in any case. The CMAC result is returned in AESAUX as well.
|
||||
static void os_aes_cmac(xref2u1_t buf, u2_t len, u1_t prepend_aux) {
|
||||
if (prepend_aux)
|
||||
lmic_aes_encrypt(AESaux, AESkey);
|
||||
else
|
||||
memset (AESaux, 0, 16);
|
||||
|
||||
while (len > 0) {
|
||||
u1_t need_padding = 0;
|
||||
for (u1_t i = 0; i < 16; ++i, ++buf, --len) {
|
||||
if (len == 0) {
|
||||
// The message is padded with 0x80 and then zeroes.
|
||||
// Since zeroes are no-op for xor, we can just skip them
|
||||
// and leave AESAUX unchanged for them.
|
||||
AESaux[i] ^= 0x80;
|
||||
need_padding = 1;
|
||||
break;
|
||||
}
|
||||
AESaux[i] ^= *buf;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
// Final block, xor with K1 or K2. K1 and K2 are calculated
|
||||
// by encrypting the all-zeroes block and then applying some
|
||||
// shifts and xor on that.
|
||||
u1_t final_key[16];
|
||||
memset(final_key, 0, sizeof(final_key));
|
||||
lmic_aes_encrypt(final_key, AESkey);
|
||||
|
||||
// Calculate K1
|
||||
u1_t msb = final_key[0] & 0x80;
|
||||
shift_left(final_key, sizeof(final_key));
|
||||
if (msb)
|
||||
final_key[sizeof(final_key)-1] ^= 0x87;
|
||||
|
||||
// If the final block was not complete, calculate K2 from K1
|
||||
if (need_padding) {
|
||||
msb = final_key[0] & 0x80;
|
||||
shift_left(final_key, sizeof(final_key));
|
||||
if (msb)
|
||||
final_key[sizeof(final_key)-1] ^= 0x87;
|
||||
}
|
||||
|
||||
// Xor with K1 or K2
|
||||
for (u1_t i = 0; i < sizeof(final_key); ++i)
|
||||
AESaux[i] ^= final_key[i];
|
||||
}
|
||||
|
||||
lmic_aes_encrypt(AESaux, AESkey);
|
||||
}
|
||||
}
|
||||
|
||||
// Run AES-CTR using the key in AESKEY and using AESAUX as the
|
||||
// counter block. The last byte of the counter block will be incremented
|
||||
// for every block. The given buffer will be encrypted in place.
|
||||
static void os_aes_ctr (xref2u1_t buf, u2_t len) {
|
||||
u1_t ctr[16];
|
||||
while (len) {
|
||||
// Encrypt the counter block with the selected key
|
||||
memcpy(ctr, AESaux, sizeof(ctr));
|
||||
lmic_aes_encrypt(ctr, AESkey);
|
||||
|
||||
// Xor the payload with the resulting ciphertext
|
||||
for (u1_t i = 0; i < 16 && len > 0; i++, len--, buf++)
|
||||
*buf ^= ctr[i];
|
||||
|
||||
// Increment the block index byte
|
||||
AESaux[15]++;
|
||||
}
|
||||
}
|
||||
|
||||
u4_t os_aes (u1_t mode, xref2u1_t buf, u2_t len) {
|
||||
switch (mode & ~AES_MICNOAUX) {
|
||||
case AES_MIC:
|
||||
os_aes_cmac(buf, len, /* prepend_aux */ !(mode & AES_MICNOAUX));
|
||||
return os_rmsbf4(AESaux);
|
||||
|
||||
case AES_ENC:
|
||||
// TODO: Check / handle when len is not a multiple of 16
|
||||
for (u1_t i = 0; i < len; i += 16)
|
||||
lmic_aes_encrypt(buf+i, AESkey);
|
||||
break;
|
||||
|
||||
case AES_CTR:
|
||||
os_aes_ctr(buf, len);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // !defined(USE_ORIGINAL_AES)
|
Loading…
Reference in New Issue