Fixes to AES-CTR encryption after testing

pull/167/head
Daniele Lacamera 2022-01-31 16:46:09 +01:00
parent b656e4abef
commit 43a5a38629
8 changed files with 95 additions and 32 deletions

View File

@ -57,18 +57,27 @@ reboot.
### Symmetric encryption algorithm
The algorithm currently used to encrypt and decrypt data in external partitions
The default algorithm used to encrypt and decrypt data in external partitions
is Chacha20-256.
- The `key` provided to `wolfBoot_set_encrypt_key()` must be exactly 32 Bytes long.
- The `nonce` argument must be a 96-bit (12 Bytes) randomly generated buffer, to be used as IV for encryption and decryption.
AES-128 and AES-256 are also supported. AES is used in counter mode. AES-128 and AES-256 have a key length of 16 and 32 bytes
respectively, and the IV size is 16 bytes long in both cases.
## Example usage
### Signing and encrypting the update bundle
To compile wolfBoot with encryption support, use the option `ENCRYPT=1`.
By default, this also selects `ENCRYPT_WITH_CHACHA=1`. To use AES encryption instead,
select `ENCRYPT_WITH_AES128=1` or `ENCRYPT_WITH_AES256=1`.
### Signing and encrypting the update bundle with ChaCha20-256
The `sign.py` tool can sign and encrypt the image with a single command.
The encryption secret is provided in a binary file that should contain a concatenation of
In case of chacha20, the encryption secret is provided in a binary file that should contain a concatenation of
a 32B ChaCha-256 key and a 12B nonce.
In the examples provided, the test application uses the following parameters:
@ -94,6 +103,34 @@ secret file:
which will produce as output the file `test-app/image_v24_signed_and_encrypted.bin`, that can be transferred to the target's external device.
### Signing and encrypting the update bundle with AES-256
In case of AES-256, the encryption secret is provided in a binary file that should contain a concatenation of
a 32B key and a 16B IV.
In the examples provided, the test application uses the following parameters:
```
key = "0123456789abcdef0123456789abcdef"
iv = "0123456789abcdef"
```
So it is easy to prepare the encryption secret in the test scripts or from the command line using:
```
echo -n "0123456789abcdef0123456789abcdef0123456789abcdef" > enc_key.der
```
The `sign.py` script can now be invoked to produce a signed+encrypted image, by using the extra argument `--encrypt` followed by the
secret file. To select AES-256, use the `--aes256` option.
```
./tools/keytools/sign.py --aes256 --encrypt enc_key.der test-app/image.bin ecc256.der 24
```
which will produce as output the file `test-app/image_v24_signed_and_encrypted.bin`, that can be transferred to the target's external device.
### API usage in the application

View File

@ -149,14 +149,16 @@ int wolfBoot_dualboot_candidate(void);
#ifdef EXT_ENCRYPTED
#define ENCRYPT_BLOCK_SIZE 16
#define ENCRYPT_NONCE_SIZE 12 /* 96 bit*/
/* Encryption support */
#if defined(ENCRYPT_WITH_CHACHA)
#define ENCRYPT_KEY_SIZE 32 /* Chacha20 - 256bit */
#define ENCRYPT_NONCE_SIZE 12 /* 96 bit*/
#elif defined(ENCRYPT_WITH_AES128)
#define ENCRYPT_KEY_SIZE 16 /* AES128 */
#define ENCRYPT_NONCE_SIZE 16 /* AES IV size */
#elif defined(ENCRYPT_WITH_AES256)
#define ENCRYPT_KEY_SIZE 32 /* AES256 */
#define ENCRYPT_NONCE_SIZE 16 /* AES IV size */
#else
# error "Encryption ON, but no encryption algorithm selected."
#endif

View File

@ -181,17 +181,18 @@ endif
ifeq ($(ENCRYPT),1)
CFLAGS+=-D"EXT_ENCRYPTED=1"
ifeq ($(ENCRYPT_WITH_CHACHA),1)
ifeq ($(ENCRYPT_WITH_AES128),1)
CFLAGS+=-DWOLFSSL_AES_COUNTER -DWOLFSSL_AES_DIRECT
CFLAGS+=-DENCRYPT_WITH_AES128 -DWOLFSSL_AES_128
WOLFCRYPT_OBJS+=./lib/wolfssl/wolfcrypt/src/aes.o
else ifeq ($(ENCRYPT_WITH_AES256),1)
CFLAGS+=-DWOLFSSL_AES_COUNTER -DWOLFSSL_AES_DIRECT
CFLAGS+=-DENCRYPT_WITH_AES256 -DWOLFSSL_AES_256
WOLFCRYPT_OBJS+=./lib/wolfssl/wolfcrypt/src/aes.o
else
ENCRYPT_WITH_CHACHA=1
WOLFCRYPT_OBJS+=./lib/wolfssl/wolfcrypt/src/chacha.o
CFLAGS+=-DENCRYPT_WITH_CHACHA -DHAVE_CHACHA
else
CFLAGS+=-DWOLFSSL_AES_COUNTER -DWOLFSSL_AES_DIRECT
WOLFCRYPT_OBJS+=./lib/wolfssl/wolfcrypt/src/aes.o
endif
ifeq ($(ENCRYPT_WITH_AES128),1)
CFLAGS+=-DENCRYPT_WITH_AES128 -DWOLFSSL_AES_128
else ifeq ($(ENCRYPT_WITH_AES256),1)
CFLAGS+=-DENCRYPT_WITH_AES256 -DWOLFSSL_AES_256
endif
endif

View File

@ -818,8 +818,8 @@ static int aes_init(void)
return -1;
XMEMCPY(encrypt_iv_nonce, stored_nonce, ENCRYPT_NONCE_SIZE);
XMEMCPY(&iv_buf[1], stored_nonce, ENCRYPT_NONCE_SIZE);
iv_buf[0] = 0;
XMEMCPY(iv_buf, stored_nonce, ENCRYPT_NONCE_SIZE);
iv_buf[4] = 0;
/* AES_ENCRYPTION is used for both directions in CTR */
wc_AesSetKeyDirect(&aes_enc, key, ENCRYPT_KEY_SIZE, iv_buf, AES_ENCRYPTION);
wc_AesSetKeyDirect(&aes_dec, key, ENCRYPT_KEY_SIZE, iv_buf, AES_ENCRYPTION);
@ -830,9 +830,11 @@ static int aes_init(void)
static void aes_set_iv(byte *nonce, uint32_t iv_ctr)
{
uint32_t iv_buf[ENCRYPT_BLOCK_SIZE / sizeof(uint32_t)];
XMEMCPY(&iv_buf[1], nonce, ENCRYPT_NONCE_SIZE);
iv_buf[0] = ByteReverseWord32(iv_ctr);
uint32_t iv_local_ctr;
XMEMCPY(iv_buf, nonce, ENCRYPT_NONCE_SIZE);
iv_buf[3] = ByteReverseWord32(iv_ctr);
wc_AesSetIV(&aes_enc, (byte *)iv_buf);
wc_AesSetIV(&aes_dec, (byte *)iv_buf);
}

View File

@ -30,8 +30,15 @@
#include "uart_drv.h"
#ifdef PLATFORM_stm32wb
char enc_key[] = "0123456789abcdef0123456789abcdef" /* ChaCha key (256 bit) */
"0123456789ab"; /* IV nonce (96 bit) */
/* Matches all keys:
* - chacha (32 + 12)
* - aes128 (16 + 16)
* - aes256 (32 + 16)
*/
/* Longest key possible: AES256 (32 key + 16 IV = 48) */
char enc_key[] = "0123456789abcdef0123456789abcdef"
"0123456789abcdef";
volatile uint32_t time_elapsed = 0;
void main(void) {

View File

@ -28,6 +28,9 @@ ifeq ($(ARCH),)
V?=0
NO_MPU?=0
ENCRYPT?=0
ENCRYPT_WITH_CHACHA?=0
ENCRYPT_WITH_AES128?=0
ENCRYPT_WITH_AES256?=0
FLAGS_HOME?=0
FLAGS_INVERT?=0
SPMATH?=1
@ -61,5 +64,6 @@ CONFIG_VARS:= ARCH TARGET SIGN HASH MCUXPRESSO MCUXPRESSO_CPU MCUXPRESSO_DRIVERS
WOLFBOOT_PARTITION_BOOT_ADDRESS WOLFBOOT_PARTITION_UPDATE_ADDRESS \
WOLFBOOT_PARTITION_SWAP_ADDRESS WOLFBOOT_LOAD_ADDRESS \
WOLFBOOT_LOAD_DTS_ADDRESS WOLFBOOT_DTS_BOOT_ADDRESS WOLFBOOT_DTS_UPDATE_ADDRESS \
WOLFBOOT_SMALL_STACK DELTA_UPDATES DELTA_BLOCK_SIZE
WOLFBOOT_SMALL_STACK DELTA_UPDATES DELTA_BLOCK_SIZE \
ENCRYPT_WITH_CHAHA ENCRYPT_WITH_AES128 ENCRYPT_WITH_AES256

View File

@ -285,20 +285,14 @@ while (i < len(argv)):
encrypt_key_file = argv[i]
elif (argv[i] == '--chacha'):
encrypt = True
i += 1
encrypt_key_file = argv[i]
elif (argv[i] == '--aes128'):
encrypt = True
chacha = False
aes128 = True
i += 1
encrypt_key_file = argv[i]
elif (argv[i] == '--aes256'):
encrypt = True
chacha = False
aes256 = True
i += 1
encrypt_key_file = argv[i]
elif (argv[i] == '--delta'):
delta = True
i += 1
@ -563,21 +557,25 @@ if (encrypt):
off += 1
elif aes128:
key = ekeyfile.read(16)
iv = ekeyfile.read(16)
iv = ekeyfile.read(12) + struct.pack('<L', 0)
aesctr = ciphers.Aes(key, ciphers.MODE_CTR, iv)
while True:
buf = outfile.read(16)
if len(buf) == 0:
break
while (len(buf) % 16) != 0:
buf += struct.pack('B', HDR_PADDING)
enc_outfile.write(aesctr.encrypt(buf))
elif aes256:
key = ekeyfile.read(32)
iv = ekeyfile.read(16)
iv = ekeyfile.read(12) + struct.pack('<L', 0)
aesctr = ciphers.Aes(key, ciphers.MODE_CTR, iv)
while True:
buf = outfile.read(16)
if len(buf) == 0:
break
while (len(buf) % 16) != 0:
buf += struct.pack('B', HDR_PADDING)
enc_outfile.write(aesctr.encrypt(buf))
outfile.close()
ekeyfile.close()

View File

@ -4,6 +4,18 @@ test-enc-update:SIGN_ENC_ARGS?=--ecc256 --encrypt /tmp/enc_key.der
test-enc-update:USBTTY?=/dev/ttyACM0
test-enc-update:TIMEOUT?=60
test-enc-aes128-update:ENC_TEST_UPDATE_VERSION?=2
test-enc-aes128-update:SIGN_ARGS?=--ecc256
test-enc-aes128-update:SIGN_ENC_ARGS?=--ecc256 --aes128 --encrypt /tmp/enc_key.der
test-enc-aes128-update:USBTTY?=/dev/ttyACM0
test-enc-aes128-update:TIMEOUT?=60
test-enc-aes256-update:ENC_TEST_UPDATE_VERSION?=2
test-enc-aes256-update:SIGN_ARGS?=--ecc256
test-enc-aes256-update:SIGN_ENC_ARGS?=--ecc256 --aes256 --encrypt /tmp/enc_key.der
test-enc-aes256-update:USBTTY?=/dev/ttyACM0
test-enc-aes256-update:TIMEOUT?=60
tools/uart-flash-server/ufserver: FORCE
@make -C `dirname $@`
@rm -f src/libwolfboot.o
@ -33,10 +45,10 @@ test-enc-update: factory.bin test-app/image.bin tools/uart-flash-server/ufserver
@echo "TEST SUCCESSFUL"
test-enc-aes128-update: factory.bin test-app/image.bin tools/uart-flash-server/ufserver
@diff .config config/examples/stm32wb-uart-flash-encryption.config || (echo "\n\n*** Error: please copy config/examples/stm32wb-uart-flash-encryption.config to .config to run this test\n\n" && exit 1)
@diff .config config/examples/stm32wb-uart-flash-encryption-aes128.config || (echo "\n\n*** Error: please copy config/examples/stm32wb-uart-flash-encryption-aes128.config to .config to run this test\n\n" && exit 1)
@printf "0123456789abcdef0123456789abcdef" > /tmp/enc_key.der
@$(SIGN_TOOL) $(SIGN_ARGS) test-app/image.bin $(PRIVATE_KEY) $(ENC_TEST_UPDATE_VERSION)
@$(SIGN_TOOL) $(SIGN_ENC_ARGS) --aes128 test-app/image.bin $(PRIVATE_KEY) $(ENC_TEST_UPDATE_VERSION)
@$(SIGN_TOOL) $(SIGN_ENC_ARGS) test-app/image.bin $(PRIVATE_KEY) $(ENC_TEST_UPDATE_VERSION)
@(tools/uart-flash-server/ufserver test-app/image_v$(ENC_TEST_UPDATE_VERSION)_signed_and_encrypted.bin $(USBTTY))&
@st-flash erase
@st-flash write factory.bin 0x08000000
@ -56,10 +68,10 @@ test-enc-aes128-update: factory.bin test-app/image.bin tools/uart-flash-server/u
@echo "TEST SUCCESSFUL"
test-enc-aes256-update: factory.bin test-app/image.bin tools/uart-flash-server/ufserver
@diff .config config/examples/stm32wb-uart-flash-encryption.config || (echo "\n\n*** Error: please copy config/examples/stm32wb-uart-flash-encryption.config to .config to run this test\n\n" && exit 1)
@diff .config config/examples/stm32wb-uart-flash-encryption-aes256.config || (echo "\n\n*** Error: please copy config/examples/stm32wb-uart-flash-encryption-aes256.config to .config to run this test\n\n" && exit 1)
@printf "0123456789abcdef0123456789abcdef0123456789abcdef" > /tmp/enc_key.der
@$(SIGN_TOOL) $(SIGN_ARGS) test-app/image.bin $(PRIVATE_KEY) $(ENC_TEST_UPDATE_VERSION)
@$(SIGN_TOOL) $(SIGN_ENC_ARGS) --aes256 test-app/image.bin $(PRIVATE_KEY) $(ENC_TEST_UPDATE_VERSION)
@$(SIGN_TOOL) $(SIGN_ENC_ARGS) test-app/image.bin $(PRIVATE_KEY) $(ENC_TEST_UPDATE_VERSION)
@(tools/uart-flash-server/ufserver test-app/image_v$(ENC_TEST_UPDATE_VERSION)_signed_and_encrypted.bin $(USBTTY))&
@st-flash erase
@st-flash write factory.bin 0x08000000