mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-18 12:28:09 +00:00
feat(core): use U5 HW keys to additionally encrypt storage items
[no changelog]
This commit is contained in:
parent
f347a08fd1
commit
e060ac68c5
@ -24,17 +24,25 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum {
|
||||
SECURE_AES_KEY_DHUK,
|
||||
SECURE_AES_KEY_BHK,
|
||||
SECURE_AES_KEY_XORK,
|
||||
} secure_aes_keysel_t;
|
||||
|
||||
// Initializes secure AES module
|
||||
secbool secure_aes_init(void);
|
||||
|
||||
// Encrypts a block of data using AES-256 EBB and (DHUK xor BHK) key
|
||||
// Input and output must be aligned to 32 bits, size is in bytes
|
||||
secbool secure_aes_encrypt(uint32_t* input, size_t size, uint32_t* output);
|
||||
// Encrypts a block of data using AES-256 ECB and HW key (DHUK, BHK or XORK)
|
||||
// For optimal speed input and output should be aligned to 32 bits, size is in
|
||||
// bytes
|
||||
secbool secure_aes_ecb_encrypt_hw(const uint8_t* input, size_t size,
|
||||
uint8_t* output, secure_aes_keysel_t key);
|
||||
|
||||
// Decrypts a block of data using AES-256 ECB and (DHUK xor BHK) key
|
||||
// Input and output must be aligned to 32 bits, size is in bytes
|
||||
secbool secure_aes_decrypt(uint32_t* input, size_t size, uint32_t* output);
|
||||
|
||||
void secure_aes_test();
|
||||
// Decrypts a block of data using AES-256 ECB and HW key (DHUK, BHK or XORK)
|
||||
// For optimal speed input and output should be aligned to 32 bits, size is in
|
||||
// bytes
|
||||
secbool secure_aes_ecb_decrypt_hw(const uint8_t* input, size_t size,
|
||||
uint8_t* output, secure_aes_keysel_t key);
|
||||
|
||||
#endif // TREZOR_HAL_SECURE_AES_H
|
||||
|
@ -22,6 +22,10 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stm32u5xx_hal_cryp.h>
|
||||
#include <string.h>
|
||||
#include "memzero.h"
|
||||
|
||||
#define AES_BLOCK_SIZE 16
|
||||
|
||||
secbool secure_aes_init(void) {
|
||||
RCC_OscInitTypeDef osc_init_def = {0};
|
||||
@ -50,46 +54,33 @@ static void secure_aes_load_bhk(void) {
|
||||
TAMP->BKP7R;
|
||||
}
|
||||
|
||||
secbool secure_aes_encrypt(uint32_t* input, size_t size, uint32_t* output) {
|
||||
CRYP_HandleTypeDef hcryp = {0};
|
||||
uint32_t iv[] = {0, 0, 0, 0};
|
||||
|
||||
hcryp.Instance = SAES;
|
||||
hcryp.Init.DataType = CRYP_NO_SWAP;
|
||||
hcryp.Init.KeySelect = CRYP_KEYSEL_HSW;
|
||||
hcryp.Init.KeySize = CRYP_KEYSIZE_256B;
|
||||
hcryp.Init.pKey = NULL;
|
||||
hcryp.Init.pInitVect = iv;
|
||||
hcryp.Init.Algorithm = CRYP_AES_ECB;
|
||||
hcryp.Init.Header = NULL;
|
||||
hcryp.Init.HeaderSize = 0;
|
||||
hcryp.Init.DataWidthUnit = CRYP_DATAWIDTHUNIT_WORD;
|
||||
hcryp.Init.HeaderWidthUnit = CRYP_HEADERWIDTHUNIT_BYTE;
|
||||
hcryp.Init.KeyIVConfigSkip = CRYP_KEYIVCONFIG_ALWAYS;
|
||||
hcryp.Init.KeyMode = CRYP_KEYMODE_NORMAL;
|
||||
|
||||
if (HAL_CRYP_Init(&hcryp) != HAL_OK) {
|
||||
return secfalse;
|
||||
static uint32_t get_keysel(secure_aes_keysel_t key) {
|
||||
switch (key) {
|
||||
case SECURE_AES_KEY_DHUK:
|
||||
return CRYP_KEYSEL_HW;
|
||||
case SECURE_AES_KEY_BHK:
|
||||
return CRYP_KEYSEL_SW;
|
||||
case SECURE_AES_KEY_XORK:
|
||||
return CRYP_KEYSEL_HSW;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
secure_aes_load_bhk();
|
||||
|
||||
if (HAL_CRYP_Encrypt(&hcryp, input, size, output, HAL_MAX_DELAY) != HAL_OK) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
HAL_CRYP_DeInit(&hcryp);
|
||||
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
secbool secure_aes_decrypt(uint32_t* input, size_t size, uint32_t* output) {
|
||||
secbool secure_aes_ecb_encrypt_hw(const uint8_t* input, size_t size,
|
||||
uint8_t* output, secure_aes_keysel_t key) {
|
||||
CRYP_HandleTypeDef hcryp = {0};
|
||||
uint32_t iv[] = {0, 0, 0, 0};
|
||||
|
||||
if (size % AES_BLOCK_SIZE != 0) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
uint32_t keysel = get_keysel(key);
|
||||
|
||||
hcryp.Instance = SAES;
|
||||
hcryp.Init.DataType = CRYP_NO_SWAP;
|
||||
hcryp.Init.KeySelect = CRYP_KEYSEL_HSW;
|
||||
hcryp.Init.KeySelect = keysel;
|
||||
hcryp.Init.KeySize = CRYP_KEYSIZE_256B;
|
||||
hcryp.Init.pKey = NULL;
|
||||
hcryp.Init.pInitVect = iv;
|
||||
@ -105,10 +96,103 @@ secbool secure_aes_decrypt(uint32_t* input, size_t size, uint32_t* output) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
secure_aes_load_bhk();
|
||||
if (keysel == CRYP_KEYSEL_HSW || keysel == CRYP_KEYSEL_SW) {
|
||||
secure_aes_load_bhk();
|
||||
}
|
||||
|
||||
if (HAL_CRYP_Decrypt(&hcryp, input, size, output, HAL_MAX_DELAY) != HAL_OK) {
|
||||
return secfalse;
|
||||
if ((size_t)input % sizeof(uint32_t) != 0 ||
|
||||
(size_t)output % sizeof(uint32_t) != 0) {
|
||||
size_t tmp_size = size;
|
||||
while (tmp_size >= AES_BLOCK_SIZE) {
|
||||
uint32_t input_buffer[AES_BLOCK_SIZE / sizeof(uint32_t)];
|
||||
uint32_t output_buffer[AES_BLOCK_SIZE / sizeof(uint32_t)];
|
||||
memcpy(input_buffer, input, AES_BLOCK_SIZE);
|
||||
if (HAL_CRYP_Encrypt(&hcryp, input_buffer, AES_BLOCK_SIZE, output_buffer,
|
||||
HAL_MAX_DELAY) != HAL_OK) {
|
||||
memzero(input_buffer, sizeof(input_buffer));
|
||||
memzero(output_buffer, sizeof(output_buffer));
|
||||
return secfalse;
|
||||
}
|
||||
memcpy(output, output_buffer, AES_BLOCK_SIZE);
|
||||
input += AES_BLOCK_SIZE;
|
||||
output += AES_BLOCK_SIZE;
|
||||
tmp_size -= AES_BLOCK_SIZE;
|
||||
|
||||
memzero(input_buffer, sizeof(input_buffer));
|
||||
memzero(output_buffer, sizeof(output_buffer));
|
||||
}
|
||||
|
||||
} else {
|
||||
if (HAL_CRYP_Encrypt(&hcryp, (uint32_t*)input, size, (uint32_t*)output,
|
||||
HAL_MAX_DELAY) != HAL_OK) {
|
||||
return secfalse;
|
||||
}
|
||||
}
|
||||
|
||||
HAL_CRYP_DeInit(&hcryp);
|
||||
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
secbool secure_aes_ecb_decrypt_hw(const uint8_t* input, size_t size,
|
||||
uint8_t* output, secure_aes_keysel_t key) {
|
||||
CRYP_HandleTypeDef hcryp = {0};
|
||||
uint32_t iv[] = {0, 0, 0, 0};
|
||||
|
||||
if (size % AES_BLOCK_SIZE != 0) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
uint32_t keysel = get_keysel(key);
|
||||
|
||||
hcryp.Instance = SAES;
|
||||
hcryp.Init.DataType = CRYP_NO_SWAP;
|
||||
hcryp.Init.KeySelect = keysel;
|
||||
hcryp.Init.KeySize = CRYP_KEYSIZE_256B;
|
||||
hcryp.Init.pKey = NULL;
|
||||
hcryp.Init.pInitVect = iv;
|
||||
hcryp.Init.Algorithm = CRYP_AES_ECB;
|
||||
hcryp.Init.Header = NULL;
|
||||
hcryp.Init.HeaderSize = 0;
|
||||
hcryp.Init.DataWidthUnit = CRYP_DATAWIDTHUNIT_BYTE;
|
||||
hcryp.Init.HeaderWidthUnit = CRYP_HEADERWIDTHUNIT_BYTE;
|
||||
hcryp.Init.KeyIVConfigSkip = CRYP_KEYIVCONFIG_ALWAYS;
|
||||
hcryp.Init.KeyMode = CRYP_KEYMODE_NORMAL;
|
||||
|
||||
if (HAL_CRYP_Init(&hcryp) != HAL_OK) {
|
||||
return secfalse;
|
||||
}
|
||||
if (keysel == CRYP_KEYSEL_HSW || keysel == CRYP_KEYSEL_SW) {
|
||||
secure_aes_load_bhk();
|
||||
}
|
||||
|
||||
if ((size_t)input % sizeof(uint32_t) != 0 ||
|
||||
(size_t)output % sizeof(uint32_t) != 0) {
|
||||
size_t tmp_size = size;
|
||||
while (tmp_size >= AES_BLOCK_SIZE) {
|
||||
uint32_t input_buffer[AES_BLOCK_SIZE / sizeof(uint32_t)];
|
||||
uint32_t output_buffer[AES_BLOCK_SIZE / sizeof(uint32_t)];
|
||||
memcpy(input_buffer, input, AES_BLOCK_SIZE);
|
||||
if (HAL_CRYP_Decrypt(&hcryp, input_buffer, AES_BLOCK_SIZE, output_buffer,
|
||||
HAL_MAX_DELAY) != HAL_OK) {
|
||||
memzero(input_buffer, sizeof(input_buffer));
|
||||
memzero(output_buffer, sizeof(output_buffer));
|
||||
return secfalse;
|
||||
}
|
||||
memcpy(output, output_buffer, AES_BLOCK_SIZE);
|
||||
input += AES_BLOCK_SIZE;
|
||||
output += AES_BLOCK_SIZE;
|
||||
tmp_size -= AES_BLOCK_SIZE;
|
||||
|
||||
memzero(input_buffer, sizeof(input_buffer));
|
||||
memzero(output_buffer, sizeof(output_buffer));
|
||||
}
|
||||
|
||||
} else {
|
||||
if (HAL_CRYP_Decrypt(&hcryp, (uint32_t*)input, size, (uint32_t*)output,
|
||||
HAL_MAX_DELAY) != HAL_OK) {
|
||||
return secfalse;
|
||||
}
|
||||
}
|
||||
|
||||
HAL_CRYP_DeInit(&hcryp);
|
||||
|
@ -36,6 +36,10 @@
|
||||
#include "optiga.h"
|
||||
#endif
|
||||
|
||||
#ifdef STM32U5
|
||||
#include "secure_aes.h"
|
||||
#endif
|
||||
|
||||
// The APP namespace which is reserved for storage related values.
|
||||
#define APP_STORAGE 0x00
|
||||
|
||||
@ -491,7 +495,17 @@ static void derive_kek(const uint8_t *pin, size_t pin_len,
|
||||
pbkdf2_hmac_sha256_Update(&ctx, PIN_ITER_COUNT / 10);
|
||||
ui_progress(PIN_PBKDF2_MS / 10);
|
||||
}
|
||||
|
||||
#ifdef STM32U5
|
||||
uint8_t pre_kek[SHA256_DIGEST_LENGTH] = {0};
|
||||
pbkdf2_hmac_sha256_Final(&ctx, pre_kek);
|
||||
ensure(secure_aes_ecb_encrypt_hw(pre_kek, SHA256_DIGEST_LENGTH, kek,
|
||||
SECURE_AES_KEY_XORK),
|
||||
"secure_aes derive kek failed");
|
||||
memzero(pre_kek, sizeof(pre_kek));
|
||||
#else
|
||||
pbkdf2_hmac_sha256_Final(&ctx, kek);
|
||||
#endif
|
||||
|
||||
pbkdf2_hmac_sha256_Init(&ctx, pin, pin_len, salt, salt_len, 2);
|
||||
for (int i = 6; i <= 10; i++) {
|
||||
@ -541,8 +555,16 @@ static void stretch_pin_optiga(const uint8_t *pin, size_t pin_len,
|
||||
pbkdf2_hmac_sha256_Update(&ctx, PIN_ITER_COUNT / 10);
|
||||
ui_progress(PIN_PBKDF2_MS / 10);
|
||||
}
|
||||
#ifdef STM32U5
|
||||
uint8_t stretched_pin_tmp[OPTIGA_PIN_SECRET_SIZE] = {0};
|
||||
pbkdf2_hmac_sha256_Final(&ctx, stretched_pin_tmp);
|
||||
ensure(secure_aes_ecb_encrypt_hw(stretched_pin_tmp, OPTIGA_PIN_SECRET_SIZE,
|
||||
stretched_pin, SECURE_AES_KEY_XORK),
|
||||
"secure_aes pin stretch failed");
|
||||
memzero(stretched_pin_tmp, sizeof(stretched_pin_tmp));
|
||||
#else
|
||||
pbkdf2_hmac_sha256_Final(&ctx, stretched_pin);
|
||||
|
||||
#endif
|
||||
memzero(&ctx, sizeof(ctx));
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user