mirror of https://github.com/wolfSSL/wolfBoot.git
commit
262a5b0a78
|
@ -0,0 +1,30 @@
|
||||||
|
ARCH?=ARM
|
||||||
|
TARGET?=stm32wb
|
||||||
|
SIGN?=ECC256
|
||||||
|
HASH?=SHA256
|
||||||
|
DEBUG?=0
|
||||||
|
VTOR?=1
|
||||||
|
CORTEX_M0?=0
|
||||||
|
NO_ASM?=0
|
||||||
|
EXT_FLASH?=1
|
||||||
|
SPI_FLASH?=0
|
||||||
|
NO_XIP?=0
|
||||||
|
UART_FLASH?=1
|
||||||
|
ALLOW_DOWNGRADE?=0
|
||||||
|
NVM_FLASH_WRITEONCE?=1
|
||||||
|
WOLFBOOT_VERSION?=0
|
||||||
|
V?=0
|
||||||
|
NO_MPU?=0
|
||||||
|
SPMATH?=1
|
||||||
|
RAM_CODE?=0
|
||||||
|
DUALBANK_SWAP?=0
|
||||||
|
IMAGE_HEADER_SIZE?=256
|
||||||
|
PKA?=0
|
||||||
|
ENCRYPT=1
|
||||||
|
ENCRYPT_WITH_AES128=1
|
||||||
|
WOLFTPM?=0
|
||||||
|
WOLFBOOT_PARTITION_SIZE?=0x20000
|
||||||
|
WOLFBOOT_SECTOR_SIZE?=0x1000
|
||||||
|
WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x08010000
|
||||||
|
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x0
|
||||||
|
WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x20000
|
|
@ -0,0 +1,30 @@
|
||||||
|
ARCH?=ARM
|
||||||
|
TARGET?=stm32wb
|
||||||
|
SIGN?=ECC256
|
||||||
|
HASH?=SHA256
|
||||||
|
DEBUG?=0
|
||||||
|
VTOR?=1
|
||||||
|
CORTEX_M0?=0
|
||||||
|
NO_ASM?=0
|
||||||
|
EXT_FLASH?=1
|
||||||
|
SPI_FLASH?=0
|
||||||
|
NO_XIP?=0
|
||||||
|
UART_FLASH?=1
|
||||||
|
ALLOW_DOWNGRADE?=0
|
||||||
|
NVM_FLASH_WRITEONCE?=1
|
||||||
|
WOLFBOOT_VERSION?=0
|
||||||
|
V?=0
|
||||||
|
NO_MPU?=0
|
||||||
|
SPMATH?=1
|
||||||
|
RAM_CODE?=0
|
||||||
|
DUALBANK_SWAP?=0
|
||||||
|
IMAGE_HEADER_SIZE?=256
|
||||||
|
PKA?=0
|
||||||
|
ENCRYPT=1
|
||||||
|
ENCRYPT_WITH_AES256=1
|
||||||
|
WOLFTPM?=0
|
||||||
|
WOLFBOOT_PARTITION_SIZE?=0x20000
|
||||||
|
WOLFBOOT_SECTOR_SIZE?=0x1000
|
||||||
|
WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x08010000
|
||||||
|
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x0
|
||||||
|
WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x20000
|
|
@ -21,6 +21,7 @@ DUALBANK_SWAP?=0
|
||||||
IMAGE_HEADER_SIZE?=256
|
IMAGE_HEADER_SIZE?=256
|
||||||
PKA?=0
|
PKA?=0
|
||||||
ENCRYPT=1
|
ENCRYPT=1
|
||||||
|
ENCRYPT_WITH_CHACHA=1
|
||||||
WOLFTPM?=0
|
WOLFTPM?=0
|
||||||
WOLFBOOT_PARTITION_SIZE?=0x20000
|
WOLFBOOT_PARTITION_SIZE?=0x20000
|
||||||
WOLFBOOT_SECTOR_SIZE?=0x1000
|
WOLFBOOT_SECTOR_SIZE?=0x1000
|
||||||
|
|
|
@ -57,18 +57,27 @@ reboot.
|
||||||
|
|
||||||
### Symmetric encryption algorithm
|
### 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.
|
is Chacha20-256.
|
||||||
|
|
||||||
- The `key` provided to `wolfBoot_set_encrypt_key()` must be exactly 32 Bytes long.
|
- 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.
|
- 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
|
## 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 `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.
|
a 32B ChaCha-256 key and a 12B nonce.
|
||||||
|
|
||||||
In the examples provided, the test application uses the following parameters:
|
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.
|
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
|
### API usage in the application
|
||||||
|
|
||||||
|
|
|
@ -31,9 +31,37 @@
|
||||||
#include "target.h"
|
#include "target.h"
|
||||||
#include "wolfboot/wolfboot.h"
|
#include "wolfboot/wolfboot.h"
|
||||||
|
|
||||||
|
#ifdef ENCRYPT_WITH_CHACHA
|
||||||
#include <wolfssl/wolfcrypt/chacha.h>
|
#include <wolfssl/wolfcrypt/chacha.h>
|
||||||
|
#else
|
||||||
|
#include <wolfssl/wolfcrypt/aes.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <wolfssl/wolfcrypt/pwdbased.h>
|
#include <wolfssl/wolfcrypt/pwdbased.h>
|
||||||
|
|
||||||
|
#ifdef ENCRYPT_WITH_CHACHA
|
||||||
|
|
||||||
|
extern ChaCha chacha;
|
||||||
|
|
||||||
|
#define crypto_init() chacha_init()
|
||||||
|
#define crypto_encrypt(eb,b,sz) wc_Chacha_Process(&chacha, eb, b, sz)
|
||||||
|
#define crypto_decrypt(db,b,sz) wc_Chacha_Process(&chacha, db, b, sz)
|
||||||
|
#define crypto_set_iv(n, iv) wc_Chacha_SetIV(&chacha, n, iv)
|
||||||
|
|
||||||
|
int chacha_init(void);
|
||||||
|
|
||||||
|
#elif defined(ENCRYPT_WITH_AES128) || defined(ENCRYPT_WITH_AES256)
|
||||||
|
|
||||||
|
extern Aes aes_dec, aes_enc;
|
||||||
|
|
||||||
|
#define crypto_init() aes_init()
|
||||||
|
#define crypto_encrypt(eb,b,sz) wc_AesCtrEncrypt(&aes_enc, eb, b, sz)
|
||||||
|
#define crypto_decrypt(db,b,sz) wc_AesCtrEncrypt(&aes_dec, db, b, sz)
|
||||||
|
#define crypto_set_iv(n,a) aes_set_iv(n, a)
|
||||||
|
|
||||||
|
int aes_init(void);
|
||||||
|
void aes_set_iv(uint8_t *nonce, uint32_t address);
|
||||||
|
#endif /* ENCRYPT_WITH_CHACHA */
|
||||||
|
|
||||||
/* Internal read/write functions (not exported in the libwolfboot API) */
|
/* Internal read/write functions (not exported in the libwolfboot API) */
|
||||||
int ext_flash_encrypt_write(uintptr_t address, const uint8_t *data, int len);
|
int ext_flash_encrypt_write(uintptr_t address, const uint8_t *data, int len);
|
||||||
|
|
|
@ -144,7 +144,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef EXT_ENCRYPTED
|
#ifdef EXT_ENCRYPTED
|
||||||
# define HAVE_CHACHA
|
|
||||||
# define HAVE_PWDBASED
|
# define HAVE_PWDBASED
|
||||||
#else
|
#else
|
||||||
# define NO_PWDBASED
|
# define NO_PWDBASED
|
||||||
|
@ -152,7 +151,9 @@
|
||||||
|
|
||||||
/* Disables - For minimum wolfCrypt build */
|
/* Disables - For minimum wolfCrypt build */
|
||||||
#ifndef WOLFBOOT_TPM
|
#ifndef WOLFBOOT_TPM
|
||||||
# define NO_AES
|
# if !defined(ENCRYPT_WITH_AES128) && !defined(ENCRYPT_WITH_AES256)
|
||||||
|
# define NO_AES
|
||||||
|
# endif
|
||||||
# define NO_HMAC
|
# define NO_HMAC
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -131,7 +131,7 @@ int wolfBoot_dualboot_candidate(void);
|
||||||
|
|
||||||
/* Hashing function configuration */
|
/* Hashing function configuration */
|
||||||
#if defined(WOLFBOOT_HASH_SHA256)
|
#if defined(WOLFBOOT_HASH_SHA256)
|
||||||
# define WOLFBOOT_SHA_BLOCK_SIZE (16)
|
# define WOLFBOOT_SHA_BLOCK_SIZE (256)
|
||||||
# define WOLFBOOT_SHA_HDR HDR_SHA256
|
# define WOLFBOOT_SHA_HDR HDR_SHA256
|
||||||
# define WOLFBOOT_SHA_DIGEST_SIZE (32)
|
# define WOLFBOOT_SHA_DIGEST_SIZE (32)
|
||||||
# define image_hash image_sha256
|
# define image_hash image_sha256
|
||||||
|
@ -146,10 +146,26 @@ int wolfBoot_dualboot_candidate(void);
|
||||||
# error "No valid hash algorithm defined!"
|
# error "No valid hash algorithm defined!"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef EXT_ENCRYPTED
|
||||||
/* Encryption support */
|
/* Encryption support */
|
||||||
#define ENCRYPT_BLOCK_SIZE 16
|
#if defined(ENCRYPT_WITH_CHACHA)
|
||||||
#define ENCRYPT_KEY_SIZE 32 /* Chacha20 - 256bit */
|
#define ENCRYPT_BLOCK_SIZE 64
|
||||||
#define ENCRYPT_NONCE_SIZE 12 /* 96 bit*/
|
#define ENCRYPT_KEY_SIZE 32 /* Chacha20 - 256bit */
|
||||||
|
#define ENCRYPT_NONCE_SIZE 12 /* 96 bit*/
|
||||||
|
#elif defined(ENCRYPT_WITH_AES128)
|
||||||
|
#define ENCRYPT_BLOCK_SIZE 16
|
||||||
|
#define ENCRYPT_KEY_SIZE 16 /* AES128 */
|
||||||
|
#define ENCRYPT_NONCE_SIZE 16 /* AES IV size */
|
||||||
|
#elif defined(ENCRYPT_WITH_AES256)
|
||||||
|
#define ENCRYPT_BLOCK_SIZE 16
|
||||||
|
#define ENCRYPT_KEY_SIZE 32 /* AES256 */
|
||||||
|
#define ENCRYPT_NONCE_SIZE 16 /* AES IV size */
|
||||||
|
#else
|
||||||
|
# error "Encryption ON, but no encryption algorithm selected."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* EXT_ENCRYPTED */
|
||||||
|
|
||||||
#ifdef DELTA_UPDATES
|
#ifdef DELTA_UPDATES
|
||||||
int wolfBoot_get_diffbase_hdr(uint8_t part, uint8_t **ptr);
|
int wolfBoot_get_diffbase_hdr(uint8_t part, uint8_t **ptr);
|
||||||
|
@ -158,4 +174,5 @@ int wolfBoot_get_diffbase_hdr(uint8_t part, uint8_t **ptr);
|
||||||
int wolfBoot_set_encrypt_key(const uint8_t *key, const uint8_t *nonce);
|
int wolfBoot_set_encrypt_key(const uint8_t *key, const uint8_t *nonce);
|
||||||
int wolfBoot_get_encrypt_key(uint8_t *key, uint8_t *nonce);
|
int wolfBoot_get_encrypt_key(uint8_t *key, uint8_t *nonce);
|
||||||
int wolfBoot_erase_encrypt_key(void);
|
int wolfBoot_erase_encrypt_key(void);
|
||||||
|
|
||||||
#endif /* !WOLFBOOT_H */
|
#endif /* !WOLFBOOT_H */
|
||||||
|
|
14
options.mk
14
options.mk
|
@ -178,7 +178,19 @@ endif
|
||||||
|
|
||||||
ifeq ($(ENCRYPT),1)
|
ifeq ($(ENCRYPT),1)
|
||||||
CFLAGS+=-D"EXT_ENCRYPTED=1"
|
CFLAGS+=-D"EXT_ENCRYPTED=1"
|
||||||
WOLFCRYPT_OBJS+=./lib/wolfssl/wolfcrypt/src/chacha.o
|
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
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(EXT_FLASH),1)
|
ifeq ($(EXT_FLASH),1)
|
||||||
|
|
|
@ -759,11 +759,14 @@ int RAMFUNCTION wolfBoot_erase_encrypt_key(void)
|
||||||
|
|
||||||
#ifdef __WOLFBOOT
|
#ifdef __WOLFBOOT
|
||||||
|
|
||||||
static ChaCha chacha;
|
static int encrypt_initialized = 0;
|
||||||
static int chacha_initialized = 0;
|
static uint8_t encrypt_iv_nonce[ENCRYPT_NONCE_SIZE];
|
||||||
static uint8_t chacha_iv_nonce[ENCRYPT_NONCE_SIZE];
|
|
||||||
|
|
||||||
static int chacha_init(void)
|
#ifdef ENCRYPT_WITH_CHACHA
|
||||||
|
|
||||||
|
ChaCha chacha;
|
||||||
|
|
||||||
|
int chacha_init(void)
|
||||||
{
|
{
|
||||||
uint8_t *key = (uint8_t *)(WOLFBOOT_PARTITION_BOOT_ADDRESS + ENCRYPT_TMP_SECRET_OFFSET);
|
uint8_t *key = (uint8_t *)(WOLFBOOT_PARTITION_BOOT_ADDRESS + ENCRYPT_TMP_SECRET_OFFSET);
|
||||||
uint8_t ff[ENCRYPT_KEY_SIZE];
|
uint8_t ff[ENCRYPT_KEY_SIZE];
|
||||||
|
@ -777,12 +780,77 @@ static int chacha_init(void)
|
||||||
if (XMEMCMP(key, ff, ENCRYPT_KEY_SIZE) == 0)
|
if (XMEMCMP(key, ff, ENCRYPT_KEY_SIZE) == 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
XMEMCPY(chacha_iv_nonce, stored_nonce, ENCRYPT_NONCE_SIZE);
|
XMEMCPY(encrypt_iv_nonce, stored_nonce, ENCRYPT_NONCE_SIZE);
|
||||||
wc_Chacha_SetKey(&chacha, key, ENCRYPT_KEY_SIZE);
|
wc_Chacha_SetKey(&chacha, key, ENCRYPT_KEY_SIZE);
|
||||||
chacha_initialized = 1;
|
encrypt_initialized = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#elif defined(ENCRYPT_WITH_AES128) || defined(ENCRYPT_WITH_AES256)
|
||||||
|
|
||||||
|
/* Inline use of ByteReverseWord32 */
|
||||||
|
#define WOLFSSL_MISC_INCLUDED
|
||||||
|
#include <wolfcrypt/src/misc.c>
|
||||||
|
|
||||||
|
Aes aes_dec, aes_enc;
|
||||||
|
|
||||||
|
int aes_init(void)
|
||||||
|
{
|
||||||
|
uint8_t *key = (uint8_t *)(WOLFBOOT_PARTITION_BOOT_ADDRESS + ENCRYPT_TMP_SECRET_OFFSET);
|
||||||
|
uint8_t ff[ENCRYPT_KEY_SIZE];
|
||||||
|
uint8_t iv_buf[ENCRYPT_BLOCK_SIZE];
|
||||||
|
uint8_t *stored_nonce = key + ENCRYPT_KEY_SIZE;
|
||||||
|
|
||||||
|
wc_AesInit(&aes_enc, NULL, 0);
|
||||||
|
wc_AesInit(&aes_dec, NULL, 0);
|
||||||
|
|
||||||
|
/* Check against 'all 0xff' or 'all zero' cases */
|
||||||
|
XMEMSET(ff, 0xFF, ENCRYPT_KEY_SIZE);
|
||||||
|
if (XMEMCMP(key, ff, ENCRYPT_KEY_SIZE) == 0)
|
||||||
|
return -1;
|
||||||
|
XMEMSET(ff, 0x00, ENCRYPT_KEY_SIZE);
|
||||||
|
if (XMEMCMP(key, ff, ENCRYPT_KEY_SIZE) == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
XMEMCPY(encrypt_iv_nonce, stored_nonce, ENCRYPT_NONCE_SIZE);
|
||||||
|
XMEMCPY(iv_buf, stored_nonce, ENCRYPT_NONCE_SIZE);
|
||||||
|
/* 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);
|
||||||
|
encrypt_initialized = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void aes_set_iv(uint8_t *nonce, uint32_t iv_ctr)
|
||||||
|
{
|
||||||
|
uint32_t iv_buf[ENCRYPT_BLOCK_SIZE / sizeof(uint32_t)];
|
||||||
|
uint32_t iv_local_ctr;
|
||||||
|
int i;
|
||||||
|
XMEMCPY(iv_buf, nonce, ENCRYPT_NONCE_SIZE);
|
||||||
|
#ifndef BIG_ENDIAN_ORDER
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
iv_buf[i] = ByteReverseWord32(iv_buf[i]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
iv_buf[3] += iv_ctr;
|
||||||
|
if(iv_buf[3] < iv_ctr) { /* overflow */
|
||||||
|
for (i = 2; i >= 0; i--) {
|
||||||
|
iv_buf[i]++;
|
||||||
|
if (iv_buf[i] != 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifndef BIG_ENDIAN_ORDER
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
iv_buf[i] = ByteReverseWord32(iv_buf[i]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
wc_AesSetIV(&aes_enc, (byte *)iv_buf);
|
||||||
|
wc_AesSetIV(&aes_dec, (byte *)iv_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static inline uint8_t part_address(uintptr_t a)
|
static inline uint8_t part_address(uintptr_t a)
|
||||||
{
|
{
|
||||||
|
@ -790,20 +858,19 @@ static inline uint8_t part_address(uintptr_t a)
|
||||||
#if WOLFBOOT_PARTITION_UPDATE_ADDRESS != 0
|
#if WOLFBOOT_PARTITION_UPDATE_ADDRESS != 0
|
||||||
(a >= WOLFBOOT_PARTITION_UPDATE_ADDRESS) &&
|
(a >= WOLFBOOT_PARTITION_UPDATE_ADDRESS) &&
|
||||||
#endif
|
#endif
|
||||||
(a <= WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE))
|
(a < WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE))
|
||||||
return PART_UPDATE;
|
return PART_UPDATE;
|
||||||
if ( 1 &&
|
if ( 1 &&
|
||||||
#if WOLFBOOT_PARTITION_SWAP_ADDRESS != 0
|
#if WOLFBOOT_PARTITION_SWAP_ADDRESS != 0
|
||||||
(a >= WOLFBOOT_PARTITION_SWAP_ADDRESS) &&
|
(a >= WOLFBOOT_PARTITION_SWAP_ADDRESS) &&
|
||||||
#endif
|
#endif
|
||||||
(a <= WOLFBOOT_PARTITION_SWAP_ADDRESS + WOLFBOOT_SECTOR_SIZE))
|
(a < WOLFBOOT_PARTITION_SWAP_ADDRESS + WOLFBOOT_SECTOR_SIZE))
|
||||||
return PART_SWAP;
|
return PART_SWAP;
|
||||||
return PART_NONE;
|
return PART_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ext_flash_encrypt_write(uintptr_t address, const uint8_t *data, int len)
|
int ext_flash_encrypt_write(uintptr_t address, const uint8_t *data, int len)
|
||||||
{
|
{
|
||||||
uint32_t iv_counter;
|
|
||||||
uint8_t block[ENCRYPT_BLOCK_SIZE];
|
uint8_t block[ENCRYPT_BLOCK_SIZE];
|
||||||
uint8_t part;
|
uint8_t part;
|
||||||
int sz = len;
|
int sz = len;
|
||||||
|
@ -818,25 +885,20 @@ int ext_flash_encrypt_write(uintptr_t address, const uint8_t *data, int len)
|
||||||
if (sz < ENCRYPT_BLOCK_SIZE) {
|
if (sz < ENCRYPT_BLOCK_SIZE) {
|
||||||
sz = ENCRYPT_BLOCK_SIZE;
|
sz = ENCRYPT_BLOCK_SIZE;
|
||||||
}
|
}
|
||||||
if (!chacha_initialized)
|
if (!encrypt_initialized)
|
||||||
if (chacha_init() < 0)
|
if (crypto_init() < 0)
|
||||||
return -1;
|
return -1;
|
||||||
part = part_address(address);
|
part = part_address(address);
|
||||||
switch(part) {
|
switch(part) {
|
||||||
case PART_UPDATE:
|
case PART_UPDATE:
|
||||||
iv_counter = (address - WOLFBOOT_PARTITION_UPDATE_ADDRESS) / ENCRYPT_BLOCK_SIZE;
|
/* do not encrypt flag sector */
|
||||||
/* Do not encrypt last sectors */
|
if (address - WOLFBOOT_PARTITION_UPDATE_ADDRESS >= START_FLAGS_OFFSET) {
|
||||||
if (iv_counter >= (START_FLAGS_OFFSET - ENCRYPT_BLOCK_SIZE) / ENCRYPT_BLOCK_SIZE) {
|
|
||||||
return ext_flash_write(address, data, len);
|
return ext_flash_write(address, data, len);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PART_SWAP:
|
case PART_SWAP:
|
||||||
{
|
/* data is coming from update and is already encrypted */
|
||||||
uint32_t row_number;
|
return ext_flash_write(address, data, len);
|
||||||
row_number = (address - WOLFBOOT_PARTITION_SWAP_ADDRESS) / ENCRYPT_BLOCK_SIZE;
|
|
||||||
iv_counter = row_number;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -845,19 +907,15 @@ int ext_flash_encrypt_write(uintptr_t address, const uint8_t *data, int len)
|
||||||
if (ext_flash_read(row_address, block, ENCRYPT_BLOCK_SIZE) != ENCRYPT_BLOCK_SIZE)
|
if (ext_flash_read(row_address, block, ENCRYPT_BLOCK_SIZE) != ENCRYPT_BLOCK_SIZE)
|
||||||
return -1;
|
return -1;
|
||||||
XMEMCPY(block + row_offset, data, step);
|
XMEMCPY(block + row_offset, data, step);
|
||||||
wc_Chacha_SetIV(&chacha, chacha_iv_nonce, iv_counter);
|
crypto_encrypt(enc_block, block, ENCRYPT_BLOCK_SIZE);
|
||||||
wc_Chacha_Process(&chacha, enc_block, block, ENCRYPT_BLOCK_SIZE);
|
|
||||||
ext_flash_write(row_address, enc_block, ENCRYPT_BLOCK_SIZE);
|
ext_flash_write(row_address, enc_block, ENCRYPT_BLOCK_SIZE);
|
||||||
address += step;
|
address += step;
|
||||||
data += step;
|
data += step;
|
||||||
sz -= step;
|
sz -= step;
|
||||||
iv_counter++;
|
|
||||||
}
|
}
|
||||||
for (i = 0; i < sz / ENCRYPT_BLOCK_SIZE; i++) {
|
for (i = 0; i < sz / ENCRYPT_BLOCK_SIZE; i++) {
|
||||||
wc_Chacha_SetIV(&chacha, chacha_iv_nonce, iv_counter);
|
|
||||||
XMEMCPY(block, data + (ENCRYPT_BLOCK_SIZE * i), ENCRYPT_BLOCK_SIZE);
|
XMEMCPY(block, data + (ENCRYPT_BLOCK_SIZE * i), ENCRYPT_BLOCK_SIZE);
|
||||||
wc_Chacha_Process(&chacha, ENCRYPT_CACHE + (ENCRYPT_BLOCK_SIZE * i), block, ENCRYPT_BLOCK_SIZE);
|
crypto_encrypt(ENCRYPT_CACHE + (ENCRYPT_BLOCK_SIZE * i), block, ENCRYPT_BLOCK_SIZE);
|
||||||
iv_counter++;
|
|
||||||
}
|
}
|
||||||
return ext_flash_write(address, ENCRYPT_CACHE, len);
|
return ext_flash_write(address, ENCRYPT_CACHE, len);
|
||||||
}
|
}
|
||||||
|
@ -879,8 +937,8 @@ int ext_flash_decrypt_read(uintptr_t address, uint8_t *data, int len)
|
||||||
if (sz < ENCRYPT_BLOCK_SIZE) {
|
if (sz < ENCRYPT_BLOCK_SIZE) {
|
||||||
sz = ENCRYPT_BLOCK_SIZE;
|
sz = ENCRYPT_BLOCK_SIZE;
|
||||||
}
|
}
|
||||||
if (!chacha_initialized)
|
if (!encrypt_initialized)
|
||||||
if (chacha_init() < 0)
|
if (crypto_init() < 0)
|
||||||
return -1;
|
return -1;
|
||||||
part = part_address(row_address);
|
part = part_address(row_address);
|
||||||
switch(part) {
|
switch(part) {
|
||||||
|
@ -890,12 +948,10 @@ int ext_flash_decrypt_read(uintptr_t address, uint8_t *data, int len)
|
||||||
if (iv_counter >= (START_FLAGS_OFFSET - ENCRYPT_BLOCK_SIZE) / ENCRYPT_BLOCK_SIZE) {
|
if (iv_counter >= (START_FLAGS_OFFSET - ENCRYPT_BLOCK_SIZE) / ENCRYPT_BLOCK_SIZE) {
|
||||||
return ext_flash_read(address, data, len);
|
return ext_flash_read(address, data, len);
|
||||||
}
|
}
|
||||||
|
crypto_set_iv(encrypt_iv_nonce, iv_counter);
|
||||||
break;
|
break;
|
||||||
case PART_SWAP:
|
case PART_SWAP:
|
||||||
{
|
{
|
||||||
uint32_t row_number;
|
|
||||||
row_number = (address - WOLFBOOT_PARTITION_SWAP_ADDRESS) / ENCRYPT_BLOCK_SIZE;
|
|
||||||
iv_counter = row_number;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -906,8 +962,7 @@ int ext_flash_decrypt_read(uintptr_t address, uint8_t *data, int len)
|
||||||
int step = ENCRYPT_BLOCK_SIZE - row_offset;
|
int step = ENCRYPT_BLOCK_SIZE - row_offset;
|
||||||
if (ext_flash_read(row_address, block, ENCRYPT_BLOCK_SIZE) != ENCRYPT_BLOCK_SIZE)
|
if (ext_flash_read(row_address, block, ENCRYPT_BLOCK_SIZE) != ENCRYPT_BLOCK_SIZE)
|
||||||
return -1;
|
return -1;
|
||||||
wc_Chacha_SetIV(&chacha, chacha_iv_nonce, iv_counter);
|
crypto_decrypt(dec_block, block, ENCRYPT_BLOCK_SIZE);
|
||||||
wc_Chacha_Process(&chacha, dec_block, block, ENCRYPT_BLOCK_SIZE);
|
|
||||||
XMEMCPY(data, dec_block + row_offset, step);
|
XMEMCPY(data, dec_block + row_offset, step);
|
||||||
address += step;
|
address += step;
|
||||||
data += step;
|
data += step;
|
||||||
|
@ -917,9 +972,8 @@ int ext_flash_decrypt_read(uintptr_t address, uint8_t *data, int len)
|
||||||
if (ext_flash_read(address, data, sz) != sz)
|
if (ext_flash_read(address, data, sz) != sz)
|
||||||
return -1;
|
return -1;
|
||||||
for (i = 0; i < sz / ENCRYPT_BLOCK_SIZE; i++) {
|
for (i = 0; i < sz / ENCRYPT_BLOCK_SIZE; i++) {
|
||||||
wc_Chacha_SetIV(&chacha, chacha_iv_nonce, iv_counter);
|
|
||||||
XMEMCPY(block, data + (ENCRYPT_BLOCK_SIZE * i), ENCRYPT_BLOCK_SIZE);
|
XMEMCPY(block, data + (ENCRYPT_BLOCK_SIZE * i), ENCRYPT_BLOCK_SIZE);
|
||||||
wc_Chacha_Process(&chacha, data + (ENCRYPT_BLOCK_SIZE * i), block, ENCRYPT_BLOCK_SIZE);
|
crypto_decrypt(data + (ENCRYPT_BLOCK_SIZE * i), block, ENCRYPT_BLOCK_SIZE);
|
||||||
iv_counter++;
|
iv_counter++;
|
||||||
}
|
}
|
||||||
return len;
|
return len;
|
||||||
|
|
|
@ -42,6 +42,10 @@ static uint8_t buffer[FLASHBUFFER_SIZE];
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef EXT_ENCRYPTED
|
||||||
|
#include "encrypt.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
static void RAMFUNCTION wolfBoot_erase_bootloader(void)
|
static void RAMFUNCTION wolfBoot_erase_bootloader(void)
|
||||||
{
|
{
|
||||||
uint32_t *start = (uint32_t *)&_start_text;
|
uint32_t *start = (uint32_t *)&_start_text;
|
||||||
|
@ -116,6 +120,12 @@ static int RAMFUNCTION wolfBoot_copy_sector(struct wolfBoot_image *src, struct w
|
||||||
uint32_t pos = 0;
|
uint32_t pos = 0;
|
||||||
uint32_t src_sector_offset = (sector * WOLFBOOT_SECTOR_SIZE);
|
uint32_t src_sector_offset = (sector * WOLFBOOT_SECTOR_SIZE);
|
||||||
uint32_t dst_sector_offset = (sector * WOLFBOOT_SECTOR_SIZE);
|
uint32_t dst_sector_offset = (sector * WOLFBOOT_SECTOR_SIZE);
|
||||||
|
#ifdef EXT_ENCRYPTED
|
||||||
|
uint8_t key[ENCRYPT_KEY_SIZE];
|
||||||
|
uint8_t nonce[ENCRYPT_NONCE_SIZE];
|
||||||
|
uint32_t iv_counter;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (src == dst)
|
if (src == dst)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -123,6 +133,18 @@ static int RAMFUNCTION wolfBoot_copy_sector(struct wolfBoot_image *src, struct w
|
||||||
src_sector_offset = 0;
|
src_sector_offset = 0;
|
||||||
if (dst->part == PART_SWAP)
|
if (dst->part == PART_SWAP)
|
||||||
dst_sector_offset = 0;
|
dst_sector_offset = 0;
|
||||||
|
|
||||||
|
#ifdef EXT_ENCRYPTED
|
||||||
|
wolfBoot_get_encrypt_key(key, nonce);
|
||||||
|
if(src->part == PART_SWAP)
|
||||||
|
iv_counter = dst_sector_offset;
|
||||||
|
else
|
||||||
|
iv_counter = src_sector_offset;
|
||||||
|
|
||||||
|
iv_counter /= ENCRYPT_BLOCK_SIZE;
|
||||||
|
crypto_set_iv(nonce, iv_counter);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef EXT_FLASH
|
#ifdef EXT_FLASH
|
||||||
if (PART_IS_EXT(src)) {
|
if (PART_IS_EXT(src)) {
|
||||||
#ifndef BUFFER_DECLARED
|
#ifndef BUFFER_DECLARED
|
||||||
|
@ -131,9 +153,20 @@ static int RAMFUNCTION wolfBoot_copy_sector(struct wolfBoot_image *src, struct w
|
||||||
#endif
|
#endif
|
||||||
wb_flash_erase(dst, dst_sector_offset, WOLFBOOT_SECTOR_SIZE);
|
wb_flash_erase(dst, dst_sector_offset, WOLFBOOT_SECTOR_SIZE);
|
||||||
while (pos < WOLFBOOT_SECTOR_SIZE) {
|
while (pos < WOLFBOOT_SECTOR_SIZE) {
|
||||||
if (src_sector_offset + pos < (src->fw_size + IMAGE_HEADER_SIZE + FLASHBUFFER_SIZE)) {
|
if (src_sector_offset + pos <
|
||||||
ext_flash_check_read((uintptr_t)(src->hdr) + src_sector_offset + pos, (void *)buffer, FLASHBUFFER_SIZE);
|
(src->fw_size + IMAGE_HEADER_SIZE + FLASHBUFFER_SIZE)) {
|
||||||
wb_flash_write(dst, dst_sector_offset + pos, buffer, FLASHBUFFER_SIZE);
|
/* bypass decryption, copy encrypted data into swap */
|
||||||
|
if (dst->part == PART_SWAP) {
|
||||||
|
ext_flash_read((uintptr_t)(src->hdr) + src_sector_offset + pos,
|
||||||
|
(void *)buffer, FLASHBUFFER_SIZE);
|
||||||
|
} else {
|
||||||
|
ext_flash_check_read((uintptr_t)(src->hdr) + src_sector_offset +
|
||||||
|
pos,
|
||||||
|
(void *)buffer, FLASHBUFFER_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
wb_flash_write(dst,
|
||||||
|
dst_sector_offset + pos, buffer, FLASHBUFFER_SIZE);
|
||||||
}
|
}
|
||||||
pos += FLASHBUFFER_SIZE;
|
pos += FLASHBUFFER_SIZE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,8 +30,15 @@
|
||||||
#include "uart_drv.h"
|
#include "uart_drv.h"
|
||||||
|
|
||||||
#ifdef PLATFORM_stm32wb
|
#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;
|
volatile uint32_t time_elapsed = 0;
|
||||||
void main(void) {
|
void main(void) {
|
||||||
|
|
|
@ -28,6 +28,9 @@ ifeq ($(ARCH),)
|
||||||
V?=0
|
V?=0
|
||||||
NO_MPU?=0
|
NO_MPU?=0
|
||||||
ENCRYPT?=0
|
ENCRYPT?=0
|
||||||
|
ENCRYPT_WITH_CHACHA?=0
|
||||||
|
ENCRYPT_WITH_AES128?=0
|
||||||
|
ENCRYPT_WITH_AES256?=0
|
||||||
FLAGS_HOME?=0
|
FLAGS_HOME?=0
|
||||||
FLAGS_INVERT?=0
|
FLAGS_INVERT?=0
|
||||||
SPMATH?=1
|
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_BOOT_ADDRESS WOLFBOOT_PARTITION_UPDATE_ADDRESS \
|
||||||
WOLFBOOT_PARTITION_SWAP_ADDRESS WOLFBOOT_LOAD_ADDRESS \
|
WOLFBOOT_PARTITION_SWAP_ADDRESS WOLFBOOT_LOAD_ADDRESS \
|
||||||
WOLFBOOT_LOAD_DTS_ADDRESS WOLFBOOT_DTS_BOOT_ADDRESS WOLFBOOT_DTS_UPDATE_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
|
||||||
|
|
||||||
|
|
|
@ -11,11 +11,11 @@ CC = gcc
|
||||||
WOLFBOOTDIR = ../..
|
WOLFBOOTDIR = ../..
|
||||||
WOLFDIR = $(WOLFBOOTDIR)/lib/wolfssl/
|
WOLFDIR = $(WOLFBOOTDIR)/lib/wolfssl/
|
||||||
CFLAGS = -Wall -Wextra -Werror
|
CFLAGS = -Wall -Wextra -Werror
|
||||||
CFLAGS += -I. -DWOLFSSL_USER_SETTINGS -I$(WOLFDIR) -I$(WOLFBOOTDIR)/include
|
CFLAGS += -I. -DWOLFSSL_USER_SETTINGS -I$(WOLFDIR) -I$(WOLFBOOTDIR)/include -DWOLFBOOT_KEYTOOLS -DWOLFSSL_AES_DIRECT -DWOLFSSL_AES_COUNTER
|
||||||
|
|
||||||
# option variables
|
# option variables
|
||||||
DEBUG_FLAGS = -g -DDEBUG -DDEBUG_SIGNTOOL -DDEBUG_WOLFSSL -DDEBUG_WOLFSSL_VERBOSE
|
DEBUG_FLAGS = -g -DDEBUG -DDEBUG_SIGNTOOL -DDEBUG_WOLFSSL -DDEBUG_WOLFSSL_VERBOSE
|
||||||
OPTIMIZE = -Os
|
OPTIMIZE = -O2
|
||||||
|
|
||||||
# Options
|
# Options
|
||||||
#CFLAGS+=$(DEBUG_FLAGS)
|
#CFLAGS+=$(DEBUG_FLAGS)
|
||||||
|
@ -29,6 +29,7 @@ CFLAGS+=-DIMAGE_HEADER_SIZE=$(IMAGE_HEADER_SIZE)
|
||||||
|
|
||||||
# Sources
|
# Sources
|
||||||
SRC=$(WOLFDIR)wolfcrypt/src/asn.c \
|
SRC=$(WOLFDIR)wolfcrypt/src/asn.c \
|
||||||
|
$(WOLFDIR)wolfcrypt/src/aes.c \
|
||||||
$(WOLFDIR)wolfcrypt/src/ecc.c \
|
$(WOLFDIR)wolfcrypt/src/ecc.c \
|
||||||
$(WOLFDIR)wolfcrypt/src/coding.c \
|
$(WOLFDIR)wolfcrypt/src/coding.c \
|
||||||
$(WOLFDIR)wolfcrypt/src/chacha.c \
|
$(WOLFDIR)wolfcrypt/src/chacha.c \
|
||||||
|
|
|
@ -56,11 +56,13 @@
|
||||||
|
|
||||||
#include <wolfssl/wolfcrypt/settings.h>
|
#include <wolfssl/wolfcrypt/settings.h>
|
||||||
#include <wolfssl/wolfcrypt/asn.h>
|
#include <wolfssl/wolfcrypt/asn.h>
|
||||||
|
#include <wolfssl/wolfcrypt/aes.h>
|
||||||
|
|
||||||
#ifdef HAVE_CHACHA
|
#ifdef HAVE_CHACHA
|
||||||
#include <wolfssl/wolfcrypt/chacha.h>
|
#include <wolfssl/wolfcrypt/chacha.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef NO_RSA
|
#ifndef NO_RSA
|
||||||
#include <wolfssl/wolfcrypt/rsa.h>
|
#include <wolfssl/wolfcrypt/rsa.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -86,7 +88,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(PATH_MAX)
|
#if defined(_WIN32) && !defined(PATH_MAX)
|
||||||
#define PATH_MAX 256
|
#define PATH_MAX 256
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef IMAGE_HEADER_SIZE
|
#ifndef IMAGE_HEADER_SIZE
|
||||||
|
@ -136,7 +138,15 @@
|
||||||
#define SIGN_RSA4096 HDR_IMG_TYPE_AUTH_RSA4096
|
#define SIGN_RSA4096 HDR_IMG_TYPE_AUTH_RSA4096
|
||||||
#define SIGN_ED448 HDR_IMG_TYPE_AUTH_ED448
|
#define SIGN_ED448 HDR_IMG_TYPE_AUTH_ED448
|
||||||
|
|
||||||
|
|
||||||
|
#define ENC_OFF 0
|
||||||
|
#define ENC_CHACHA 1
|
||||||
|
#define ENC_AES128 2
|
||||||
|
#define ENC_AES256 3
|
||||||
|
|
||||||
#define ENC_BLOCK_SIZE 16
|
#define ENC_BLOCK_SIZE 16
|
||||||
|
#define ENC_MAX_KEY_SZ 32
|
||||||
|
#define ENC_MAX_IV_SZ 16
|
||||||
|
|
||||||
static void header_append_u32(uint8_t* header, uint32_t* idx, uint32_t tmp32)
|
static void header_append_u32(uint8_t* header, uint32_t* idx, uint32_t tmp32)
|
||||||
{
|
{
|
||||||
|
@ -202,6 +212,7 @@ struct cmd_options {
|
||||||
|
|
||||||
static struct cmd_options CMD = {
|
static struct cmd_options CMD = {
|
||||||
.sign = SIGN_AUTO,
|
.sign = SIGN_AUTO,
|
||||||
|
.encrypt = ENC_OFF,
|
||||||
.hash_algo = HASH_SHA256,
|
.hash_algo = HASH_SHA256,
|
||||||
.header_sz = IMAGE_HEADER_SIZE
|
.header_sz = IMAGE_HEADER_SIZE
|
||||||
};
|
};
|
||||||
|
@ -710,28 +721,45 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz, cons
|
||||||
pos += read_sz;
|
pos += read_sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CMD.encrypt && CMD.encrypt_key_file) {
|
if ((CMD.encrypt != ENC_OFF) && CMD.encrypt_key_file) {
|
||||||
uint8_t key[CHACHA_MAX_KEY_SZ], iv[CHACHA_IV_BYTES];
|
uint8_t key[ENC_MAX_KEY_SZ], iv[ENC_MAX_IV_SZ];
|
||||||
uint8_t enc_buf[ENC_BLOCK_SIZE];
|
uint8_t enc_buf[ENC_BLOCK_SIZE];
|
||||||
int ivSz, keySz;
|
int ivSz, keySz;
|
||||||
uint32_t fsize = 0;
|
uint32_t fsize = 0;
|
||||||
ChaCha cha;
|
switch (CMD.encrypt) {
|
||||||
#ifndef HAVE_CHACHA
|
case ENC_CHACHA:
|
||||||
fprintf(stderr, "Encryption not supported: chacha support not found in wolfssl configuration.\n");
|
ivSz = CHACHA_IV_BYTES;
|
||||||
exit(100);
|
keySz = CHACHA_MAX_KEY_SZ;
|
||||||
#endif
|
break;
|
||||||
|
case ENC_AES128:
|
||||||
|
ivSz = 16;
|
||||||
|
keySz = 16;
|
||||||
|
break;
|
||||||
|
case ENC_AES256:
|
||||||
|
ivSz = 16;
|
||||||
|
keySz = 32;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("No valid encryption mode selected\n");
|
||||||
|
goto failure;
|
||||||
|
|
||||||
|
}
|
||||||
fek = fopen(CMD.encrypt_key_file, "rb");
|
fek = fopen(CMD.encrypt_key_file, "rb");
|
||||||
if (fek == NULL) {
|
if (fek == NULL) {
|
||||||
fprintf(stderr, "Open encryption key file %s: %s\n", CMD.encrypt_key_file, strerror(errno));
|
fprintf(stderr, "Open encryption key file %s: %s\n", CMD.encrypt_key_file, strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
keySz = fread(key, 1, sizeof(key), fek);
|
ret = fread(key, 1, keySz, fek);
|
||||||
ivSz = fread(iv, 1, sizeof(iv), fek);
|
if (ret != keySz) {
|
||||||
fclose(fek);
|
fprintf(stderr, "Error reading key from %s\n", CMD.encrypt_key_file);
|
||||||
if (keySz != sizeof(key) || ivSz != sizeof(iv)) {
|
|
||||||
fprintf(stderr, "Error reading key and iv from %s\n", CMD.encrypt_key_file);
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
ret = fread(iv, 1, ivSz, fek);
|
||||||
|
if (ret != ivSz) {
|
||||||
|
fprintf(stderr, "Error reading IV from %s\n", CMD.encrypt_key_file);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
fclose(fek);
|
||||||
|
|
||||||
fef = fopen(CMD.output_encrypted_image_file, "wb");
|
fef = fopen(CMD.output_encrypted_image_file, "wb");
|
||||||
if (!fef) {
|
if (!fef) {
|
||||||
|
@ -740,16 +768,40 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz, cons
|
||||||
fsize = ftell(f);
|
fsize = ftell(f);
|
||||||
fseek(f, 0, SEEK_SET); /* restart the _signed file from 0 */
|
fseek(f, 0, SEEK_SET); /* restart the _signed file from 0 */
|
||||||
|
|
||||||
wc_Chacha_SetKey(&cha, key, sizeof(key));
|
if (CMD.encrypt == ENC_CHACHA) {
|
||||||
for (pos = 0; pos < fsize; pos += ENC_BLOCK_SIZE) {
|
ChaCha cha;
|
||||||
int fread_retval;
|
#ifndef HAVE_CHACHA
|
||||||
fread_retval = fread(buf, 1, ENC_BLOCK_SIZE, f);
|
fprintf(stderr, "Encryption not supported: chacha support not found in wolfssl configuration.\n");
|
||||||
if ((fread_retval == 0) && feof(f)) {
|
exit(100);
|
||||||
break;
|
#endif
|
||||||
|
wc_Chacha_SetKey(&cha, key, sizeof(key));
|
||||||
|
wc_Chacha_SetIV(&cha, iv, 0);
|
||||||
|
for (pos = 0; pos < fsize; pos += ENC_BLOCK_SIZE) {
|
||||||
|
int fread_retval;
|
||||||
|
fread_retval = fread(buf, 1, ENC_BLOCK_SIZE, f);
|
||||||
|
if ((fread_retval == 0) && feof(f)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
wc_Chacha_Process(&cha, enc_buf, buf, fread_retval);
|
||||||
|
fwrite(enc_buf, 1, fread_retval, fef);
|
||||||
|
}
|
||||||
|
} else if ((CMD.encrypt == ENC_AES128) || (CMD.encrypt == ENC_AES256)) {
|
||||||
|
Aes aes_e;
|
||||||
|
wc_AesInit(&aes_e, NULL, 0);
|
||||||
|
wc_AesSetKeyDirect(&aes_e, key, keySz, iv, AES_ENCRYPTION);
|
||||||
|
for (pos = 0; pos < fsize; pos += ENC_BLOCK_SIZE) {
|
||||||
|
int fread_retval;
|
||||||
|
fread_retval = fread(buf, 1, ENC_BLOCK_SIZE, f);
|
||||||
|
if ((fread_retval == 0) && feof(f)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Pad with FF if input is too short */
|
||||||
|
while((fread_retval % ENC_BLOCK_SIZE) != 0) {
|
||||||
|
buf[fread_retval++] = 0xFF;
|
||||||
|
}
|
||||||
|
wc_AesCtrEncrypt(&aes_e, enc_buf, buf, fread_retval);
|
||||||
|
fwrite(enc_buf, 1, fread_retval, fef);
|
||||||
}
|
}
|
||||||
wc_Chacha_SetIV(&cha, iv, (pos >> 4));
|
|
||||||
wc_Chacha_Process(&cha, enc_buf, buf, fread_retval);
|
|
||||||
fwrite(enc_buf, 1, fread_retval, fef);
|
|
||||||
}
|
}
|
||||||
fclose(fef);
|
fclose(fef);
|
||||||
}
|
}
|
||||||
|
@ -757,7 +809,6 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz, cons
|
||||||
ret = 0;
|
ret = 0;
|
||||||
fclose(f2);
|
fclose(f2);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
failure:
|
failure:
|
||||||
if (header)
|
if (header)
|
||||||
free(header);
|
free(header);
|
||||||
|
@ -1012,7 +1063,7 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
/* Check arguments and print usage */
|
/* Check arguments and print usage */
|
||||||
if (argc < 4 || argc > 10) {
|
if (argc < 4 || argc > 10) {
|
||||||
printf("Usage: %s [--ed25519 | --ed447 | --ecc256 | --rsa2048 | --rsa2048enc | --rsa4096 | --rsa4096enc | --no-CMD.sign] [--sha256 | --sha3] [--wolfboot-update] [--encrypt enc_key.bin] [--delta image_vX_signed.bin] image key.der fw_version\n", argv[0]);
|
printf("Usage: %s [--ed25519 | --ed447 | --ecc256 | --rsa2048 | --rsa2048enc | --rsa4096 | --rsa4096enc | --no-CMD.sign] [--sha256 | --sha3] [--wolfboot-update] [--encrypt enc_key.bin] [--chacha | --aes128 | --aes256] [--delta image_vX_signed.bin] image key.der fw_version\n", argv[0]);
|
||||||
printf(" - or - ");
|
printf(" - or - ");
|
||||||
printf(" %s [--sha256 | --sha3] [--sha-only] [--wolfboot-update] image pub_key.der fw_version\n", argv[0]);
|
printf(" %s [--sha256 | --sha3] [--sha-only] [--wolfboot-update] image pub_key.der fw_version\n", argv[0]);
|
||||||
printf(" - or - ");
|
printf(" - or - ");
|
||||||
|
@ -1072,12 +1123,24 @@ int main(int argc, char** argv)
|
||||||
CMD.manual_sign = 1;
|
CMD.manual_sign = 1;
|
||||||
}
|
}
|
||||||
else if (strcmp(argv[i], "--encrypt") == 0) {
|
else if (strcmp(argv[i], "--encrypt") == 0) {
|
||||||
CMD.encrypt = 1;
|
if (CMD.encrypt == ENC_OFF)
|
||||||
|
CMD.encrypt = ENC_CHACHA;
|
||||||
CMD.encrypt_key_file = argv[++i];
|
CMD.encrypt_key_file = argv[++i];
|
||||||
} else if (strcmp(argv[i], "--delta") == 0) {
|
}
|
||||||
|
else if (strcmp(argv[i], "--aes128") == 0) {
|
||||||
|
CMD.encrypt = ENC_AES128;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[i], "--aes256") == 0) {
|
||||||
|
CMD.encrypt = ENC_AES256;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[i], "--chacha") == 0) {
|
||||||
|
CMD.encrypt = ENC_CHACHA;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[i], "--delta") == 0) {
|
||||||
CMD.delta = 1;
|
CMD.delta = 1;
|
||||||
CMD.delta_base_file = argv[++i];
|
CMD.delta_base_file = argv[++i];
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
i--;
|
i--;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,9 @@ self_update=False
|
||||||
sha_only=False
|
sha_only=False
|
||||||
manual_sign=False
|
manual_sign=False
|
||||||
encrypt=False
|
encrypt=False
|
||||||
|
chacha=True
|
||||||
|
aes128=False
|
||||||
|
aes256=False
|
||||||
delta=False
|
delta=False
|
||||||
encrypt_key_file=None
|
encrypt_key_file=None
|
||||||
delta_base_file=None
|
delta_base_file=None
|
||||||
|
@ -249,7 +252,7 @@ if (argc < 4) or (argc > 10):
|
||||||
print(" - or - ")
|
print(" - or - ")
|
||||||
print(" %s [--sha256 | --sha3] [--sha-only] [--wolfboot-update] [--encrypt key.bin] [--delta base_file.bin] image pub_key.der fw_version\n" % sys.argv[0])
|
print(" %s [--sha256 | --sha3] [--sha-only] [--wolfboot-update] [--encrypt key.bin] [--delta base_file.bin] image pub_key.der fw_version\n" % sys.argv[0])
|
||||||
print(" - or - ")
|
print(" - or - ")
|
||||||
print(" %s [--ed25519 | --ed448 | --ecc256 | --rsa2048 | --rsa4096 ] [--sha256 | --sha3] [--manual-sign] [--encrypt key.bin] [--delta base_file.bin] image pub_key.der fw_version signature.sig\n" % sys.argv[0])
|
print(" %s [--ed25519 | --ed448 | --ecc256 | --rsa2048 | --rsa4096 ] [--sha256 | --sha3] [--manual-sign] [--chacha | --aes128 | --aes256 ] [--encrypt key.bin] [--delta base_file.bin] image pub_key.der fw_version signature.sig\n" % sys.argv[0])
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
i = 1
|
i = 1
|
||||||
|
@ -280,6 +283,16 @@ while (i < len(argv)):
|
||||||
encrypt = True
|
encrypt = True
|
||||||
i += 1
|
i += 1
|
||||||
encrypt_key_file = argv[i]
|
encrypt_key_file = argv[i]
|
||||||
|
elif (argv[i] == '--chacha'):
|
||||||
|
encrypt = True
|
||||||
|
elif (argv[i] == '--aes128'):
|
||||||
|
encrypt = True
|
||||||
|
chacha = False
|
||||||
|
aes128 = True
|
||||||
|
elif (argv[i] == '--aes256'):
|
||||||
|
encrypt = True
|
||||||
|
chacha = False
|
||||||
|
aes256 = True
|
||||||
elif (argv[i] == '--delta'):
|
elif (argv[i] == '--delta'):
|
||||||
delta = True
|
delta = True
|
||||||
i += 1
|
i += 1
|
||||||
|
@ -552,17 +565,39 @@ if (encrypt):
|
||||||
off = 0
|
off = 0
|
||||||
outfile = open(output_image_file, 'rb')
|
outfile = open(output_image_file, 'rb')
|
||||||
ekeyfile = open(encrypt_key_file, 'rb')
|
ekeyfile = open(encrypt_key_file, 'rb')
|
||||||
key = ekeyfile.read(32)
|
|
||||||
iv_nonce = ekeyfile.read(12)
|
|
||||||
enc_outfile = open(encrypted_output_image_file, 'wb')
|
enc_outfile = open(encrypted_output_image_file, 'wb')
|
||||||
cha = ciphers.ChaCha(key, 32)
|
if chacha:
|
||||||
while(True):
|
key = ekeyfile.read(32)
|
||||||
cha.set_iv(iv_nonce, off)
|
iv_nonce = ekeyfile.read(12)
|
||||||
buf = outfile.read(16)
|
cha = ciphers.ChaCha(key, 32)
|
||||||
if len(buf) == 0:
|
cha.set_iv(iv_nonce, 0)
|
||||||
break
|
while True:
|
||||||
enc_outfile.write(cha.encrypt(buf))
|
buf = outfile.read(16)
|
||||||
off += 1
|
if len(buf) == 0:
|
||||||
|
break
|
||||||
|
enc_outfile.write(cha.encrypt(buf))
|
||||||
|
elif aes128:
|
||||||
|
key = ekeyfile.read(16)
|
||||||
|
iv = ekeyfile.read(16)
|
||||||
|
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)
|
||||||
|
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()
|
outfile.close()
|
||||||
ekeyfile.close()
|
ekeyfile.close()
|
||||||
enc_outfile.close()
|
enc_outfile.close()
|
||||||
|
|
|
@ -68,7 +68,6 @@
|
||||||
#define HAVE_CHACHA
|
#define HAVE_CHACHA
|
||||||
|
|
||||||
/* Disables */
|
/* Disables */
|
||||||
#define NO_AES
|
|
||||||
#define NO_CMAC
|
#define NO_CMAC
|
||||||
#define NO_HMAC
|
#define NO_HMAC
|
||||||
#define NO_RC4
|
#define NO_RC4
|
||||||
|
|
|
@ -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:USBTTY?=/dev/ttyACM0
|
||||||
test-enc-update:TIMEOUT?=60
|
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
|
tools/uart-flash-server/ufserver: FORCE
|
||||||
@make -C `dirname $@`
|
@make -C `dirname $@`
|
||||||
@rm -f src/libwolfboot.o
|
@rm -f src/libwolfboot.o
|
||||||
|
@ -32,3 +44,48 @@ test-enc-update: factory.bin test-app/image.bin tools/uart-flash-server/ufserver
|
||||||
@rm boot.bin boot_full.bin
|
@rm boot.bin boot_full.bin
|
||||||
@echo "TEST SUCCESSFUL"
|
@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-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) 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
|
||||||
|
@sleep 3
|
||||||
|
@sync
|
||||||
|
@st-flash reset
|
||||||
|
@sync
|
||||||
|
@sleep $(TIMEOUT)
|
||||||
|
@st-flash reset
|
||||||
|
@sleep 3
|
||||||
|
@killall ufserver
|
||||||
|
@st-flash read boot_full.bin 0x08010000 0x8000
|
||||||
|
@SIZE=`wc -c test-app/image_v$(ENC_TEST_UPDATE_VERSION)_signed.bin | cut -d" " -f 1`; \
|
||||||
|
dd if=boot_full.bin of=boot.bin bs=1 count=$$SIZE
|
||||||
|
@diff boot.bin test-app/image_v$(ENC_TEST_UPDATE_VERSION)_signed.bin || (echo "TEST FAILED" && exit 1)
|
||||||
|
@rm boot.bin boot_full.bin
|
||||||
|
@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-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) 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
|
||||||
|
@sleep 3
|
||||||
|
@sync
|
||||||
|
@st-flash reset
|
||||||
|
@sync
|
||||||
|
@sleep $(TIMEOUT)
|
||||||
|
@st-flash reset
|
||||||
|
@sleep 3
|
||||||
|
@killall ufserver
|
||||||
|
@st-flash read boot_full.bin 0x08010000 0x8000
|
||||||
|
@SIZE=`wc -c test-app/image_v$(ENC_TEST_UPDATE_VERSION)_signed.bin | cut -d" " -f 1`; \
|
||||||
|
dd if=boot_full.bin of=boot.bin bs=1 count=$$SIZE
|
||||||
|
@diff boot.bin test-app/image_v$(ENC_TEST_UPDATE_VERSION)_signed.bin || (echo "TEST FAILED" && exit 1)
|
||||||
|
@rm boot.bin boot_full.bin
|
||||||
|
@echo "TEST SUCCESSFUL"
|
||||||
|
|
Loading…
Reference in New Issue