mirror of https://github.com/wolfSSL/wolfBoot.git
Fixes to AES-CTR encryption after testing
parent
b656e4abef
commit
43a5a38629
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
19
options.mk
19
options.mk
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue