mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-07-10 00:28:07 +00:00
fix(core): use secure-unprivileged SAES XOR key for storage encryption
[no changelog]
This commit is contained in:
parent
14a89de6da
commit
bb562525fa
@ -40,6 +40,7 @@ typedef enum {
|
||||
MPU_MODE_SECRET, // + secret area (priviledeg RW)
|
||||
MPU_MODE_STORAGE, // + both storage areas (privilehed RW)
|
||||
MPU_MODE_ASSETS, // + assets (privileged RW)
|
||||
MPU_MODE_SAES, // + unprivileged SAES code
|
||||
MPU_MODE_APP, // + unprivileged DMA2D (RW) & Assets (RO)
|
||||
} mpu_mode_t;
|
||||
|
||||
|
@ -24,10 +24,17 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// only some of the keys are supported depending on execution environment
|
||||
typedef enum {
|
||||
SECURE_AES_KEY_DHUK,
|
||||
SECURE_AES_KEY_DHUK_SP, // secure-privileged
|
||||
SECURE_AES_KEY_DHUK_SN, // secure-nonprivileged
|
||||
SECURE_AES_KEY_DHUK_NP, // nonsecure-privileged
|
||||
SECURE_AES_KEY_DHUK_NN, // nonsecure-nonprivileged
|
||||
SECURE_AES_KEY_BHK,
|
||||
SECURE_AES_KEY_XORK,
|
||||
SECURE_AES_KEY_XORK_SP, // secure-privileged
|
||||
SECURE_AES_KEY_XORK_SN, // secure-nonprivileged
|
||||
SECURE_AES_KEY_XORK_NP, // nonsecure-privileged
|
||||
SECURE_AES_KEY_XORK_NN, // nonsecure-nonprivileged
|
||||
} secure_aes_keysel_t;
|
||||
|
||||
// Initializes secure AES module
|
||||
|
@ -23,10 +23,12 @@
|
||||
#ifdef SYSCALL_DISPATCH
|
||||
|
||||
__attribute__((naked, no_stack_protector)) static uint32_t _invoke_app_callback(
|
||||
uint32_t args1, uint32_t arg2, uint32_t arg3, void* callback) {
|
||||
uint32_t args1, uint32_t arg2, uint32_t arg3, void *callback) {
|
||||
__asm__ volatile(
|
||||
"push {r1-r12, lr} \n"
|
||||
|
||||
"mrs r12, PSPLIM \n" // backup unprivileged stack lim
|
||||
"push {r12} \n"
|
||||
"mrs r12, PSP \n" // reserved frame on unprivileged stack (!@#
|
||||
// TODO check PSP value???)
|
||||
"push {r12} \n"
|
||||
@ -73,7 +75,7 @@ __attribute__((naked, no_stack_protector)) static uint32_t _invoke_app_callback(
|
||||
}
|
||||
|
||||
uint32_t invoke_app_callback(uint32_t args1, uint32_t arg2, uint32_t arg3,
|
||||
void* callback) {
|
||||
void *callback) {
|
||||
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_APP);
|
||||
uint32_t retval = _invoke_app_callback(args1, arg2, arg3, callback);
|
||||
mpu_reconfig(mpu_mode);
|
||||
@ -81,13 +83,80 @@ uint32_t invoke_app_callback(uint32_t args1, uint32_t arg2, uint32_t arg3,
|
||||
}
|
||||
|
||||
__attribute__((naked, no_stack_protector)) void return_from_app_callback(
|
||||
uint32_t retval, uint32_t* msp) {
|
||||
uint32_t retval, uint32_t *msp) {
|
||||
__asm__ volatile(
|
||||
"MSR MSP, R1 \n"
|
||||
"POP {R1} \n"
|
||||
"MSR PSP, R1 \n"
|
||||
"POP {R1} \n"
|
||||
"MSR PSPLIM, R1 \n"
|
||||
"POP {R1-R12, LR} \n"
|
||||
"BX LR \n");
|
||||
}
|
||||
|
||||
__attribute__((naked, no_stack_protector)) static uint32_t _invoke_unpriv(
|
||||
uint32_t stack_addr, uint32_t stack_lim, void *callback) {
|
||||
__asm__ volatile(
|
||||
"push {r1-r12, lr} \n"
|
||||
|
||||
"mrs r12, PSPLIM \n" // backup unprivileged stack lim
|
||||
"push {r12} \n"
|
||||
"mrs r12, PSP \n" // backup unprivileged stack
|
||||
"push {r12} \n"
|
||||
|
||||
"mov r12, r0 \n" // setup stack for unprivileged call inside
|
||||
// kernel
|
||||
"sub r12, r12, #32 \n"
|
||||
"msr PSP, r12 \n"
|
||||
"msr PSPLIM, r1 \n"
|
||||
|
||||
"mov r3, #0 \n"
|
||||
|
||||
"mov r4, r3 \n" // Clear registers r4-r11
|
||||
"mov r5, r3 \n"
|
||||
"mov r6, r3 \n"
|
||||
"mov r7, r3 \n"
|
||||
"mov r8, r3 \n"
|
||||
"mov r9, r3 \n"
|
||||
"mov r10, r3 \n"
|
||||
"mov r11, r3 \n"
|
||||
|
||||
"str r3, [r12, #0] \n" // r0
|
||||
"str r3, [r12, #4] \n" // r1"
|
||||
"str r3, [r12, #8] \n" // r2"
|
||||
"str r3, [r12, #12] \n" // r3"
|
||||
"str r3, [r12, #16] \n" // r12"
|
||||
"str r3, [r12, #20] \n" // lr"
|
||||
|
||||
"bic r3, r2, #1 \n"
|
||||
"str r3, [r12, #24] \n" // return address
|
||||
|
||||
"ldr r1, = 0x01000000 \n"
|
||||
"str r1, [r12, #28] \n" // xPSR
|
||||
|
||||
"ldr r1, = 0xE000EF34 \n" // FPU->FPPCCR
|
||||
"ldr r0, [r1] \n"
|
||||
"bic r0, r0, #1 \n" // Clear LSPACT to suppress lazy stacking to
|
||||
"str r0, [r1] \n" // avoid potential PSP stack overwrite.
|
||||
|
||||
"mrs r1, CONTROL \n"
|
||||
"bic r1, r1, #4 \n" // Clear FPCA to suppress lazy stacking to
|
||||
"msr CONTROL, r1 \n" // avoid potential PSP stack overwrite.
|
||||
|
||||
// return to Secure Thread mode (use Secure PSP)
|
||||
"ldr lr, = 0xFFFFFFFD \n"
|
||||
"bx lr \n");
|
||||
}
|
||||
|
||||
extern const void _eustack;
|
||||
extern const void _sustack;
|
||||
|
||||
uint32_t invoke_unpriv(void *func) {
|
||||
uint32_t *stack = (uint32_t *)&_eustack;
|
||||
uint32_t *stack_lim = (uint32_t *)&_sustack;
|
||||
|
||||
uint32_t retval = _invoke_unpriv((uint32_t)stack, (uint32_t)stack_lim, func);
|
||||
return retval;
|
||||
}
|
||||
|
||||
#endif // SYSCALL_DISPATCH
|
||||
|
@ -50,6 +50,9 @@ uint32_t invoke_app_callback(uint32_t args1, uint32_t arg2, uint32_t arg3,
|
||||
|
||||
void return_from_app_callback(uint32_t retval, uint32_t* msp);
|
||||
|
||||
// Invokes unprivileged function run
|
||||
uint32_t invoke_unpriv(void* func);
|
||||
|
||||
#else // KERNEL_MODE
|
||||
|
||||
static inline uint32_t __attribute__((no_stack_protector))
|
||||
|
@ -310,8 +310,11 @@ mpu_mode_t mpu_reconfig(mpu_mode_t mode) {
|
||||
|
||||
// clang-format off
|
||||
switch (mode) {
|
||||
case MPU_MODE_SAES:
|
||||
SET_REGION( 5, PERIPH_BASE_NS, SIZE_512M, PERIPHERAL, YES, YES ); // Peripherals - SAES, TAMP
|
||||
break;
|
||||
default:
|
||||
SET_REGION( 5, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, YES ); // Peripherals
|
||||
SET_REGION( 5, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, YES ); // Frame buffer or display interface
|
||||
break;
|
||||
}
|
||||
// clang-format on
|
||||
@ -341,6 +344,9 @@ mpu_mode_t mpu_reconfig(mpu_mode_t mode) {
|
||||
case MPU_MODE_ASSETS:
|
||||
SET_REGION( 6, ASSETS_START, ASSETS_SIZE, FLASH_DATA, YES, NO );
|
||||
break;
|
||||
case MPU_MODE_SAES:
|
||||
SET_REGION( 6, KERNEL_FLASH_U_START, KERNEL_FLASH_U_SIZE,FLASH_CODE, NO, YES ); // Unprivileged kernal flash
|
||||
break;
|
||||
case MPU_MODE_APP:
|
||||
SET_REGION( 6, ASSETS_START, ASSETS_SIZE, FLASH_DATA, NO, YES );
|
||||
break;
|
||||
@ -356,8 +362,11 @@ mpu_mode_t mpu_reconfig(mpu_mode_t mode) {
|
||||
|
||||
// clang-format off
|
||||
switch (mode) {
|
||||
case MPU_MODE_APP:
|
||||
// REGION ADDRESS SIZE TYPE WRITE UNPRIV
|
||||
case MPU_MODE_SAES:
|
||||
SET_REGION( 7, KERNEL_RAM_U_START, KERNEL_RAM_U_SIZE, SRAM, YES, YES ); // Unprivileged kernel SRAM
|
||||
break;
|
||||
case MPU_MODE_APP:
|
||||
// DMA2D peripherals (Uprivileged, Read-Write, Non-Executable)
|
||||
SET_REGION( 7, 0x5002B000, SIZE_3K, PERIPHERAL, YES, YES );
|
||||
break;
|
||||
|
@ -255,7 +255,8 @@ static void secret_optiga_cache(void) {
|
||||
secbool secret_optiga_set(const uint8_t secret[SECRET_OPTIGA_KEY_LEN]) {
|
||||
uint8_t secret_enc[SECRET_OPTIGA_KEY_LEN] = {0};
|
||||
if (sectrue != secure_aes_ecb_encrypt_hw(secret, sizeof(secret_enc),
|
||||
secret_enc, SECURE_AES_KEY_DHUK)) {
|
||||
secret_enc,
|
||||
SECURE_AES_KEY_DHUK_SP)) {
|
||||
return secfalse;
|
||||
}
|
||||
secret_write(secret_enc, SECRET_OPTIGA_KEY_OFFSET, SECRET_OPTIGA_KEY_LEN);
|
||||
@ -282,7 +283,7 @@ secbool secret_optiga_get(uint8_t dest[SECRET_OPTIGA_KEY_LEN]) {
|
||||
}
|
||||
|
||||
secbool res = secure_aes_ecb_decrypt_hw(
|
||||
(uint8_t *)secret, SECRET_OPTIGA_KEY_LEN, dest, SECURE_AES_KEY_DHUK);
|
||||
(uint8_t *)secret, SECRET_OPTIGA_KEY_LEN, dest, SECURE_AES_KEY_DHUK_SP);
|
||||
|
||||
memzero(secret, sizeof(secret));
|
||||
return res;
|
||||
|
@ -17,33 +17,24 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <mpu.h>
|
||||
#include <secure_aes.h>
|
||||
#include STM32_HAL_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stm32u5xx_hal_cryp.h>
|
||||
#include <string.h>
|
||||
#include "model.h"
|
||||
#include "syscall.h"
|
||||
|
||||
#include "memzero.h"
|
||||
|
||||
#define KERNEL_UNPRIVILEGED_SIZE 32
|
||||
#define AES_BLOCK_SIZE 16
|
||||
|
||||
#ifdef KERNEL_MODE
|
||||
|
||||
#define AES_BLOCK_SIZE 16
|
||||
|
||||
secbool secure_aes_init(void) {
|
||||
RCC_OscInitTypeDef osc_init_def = {0};
|
||||
osc_init_def.OscillatorType = RCC_OSCILLATORTYPE_SHSI;
|
||||
osc_init_def.SHSIState = RCC_SHSI_ON;
|
||||
|
||||
// Enable SHSI clock
|
||||
if (HAL_RCC_OscConfig(&osc_init_def) != HAL_OK) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
// Enable SAES peripheral clock
|
||||
__HAL_RCC_SAES_CLK_ENABLE();
|
||||
|
||||
return sectrue;
|
||||
}
|
||||
#include "irq.h"
|
||||
|
||||
static void secure_aes_load_bhk(void) {
|
||||
TAMP->BKP0R;
|
||||
@ -58,19 +49,182 @@ static void secure_aes_load_bhk(void) {
|
||||
|
||||
static uint32_t get_keysel(secure_aes_keysel_t key) {
|
||||
switch (key) {
|
||||
case SECURE_AES_KEY_DHUK:
|
||||
case SECURE_AES_KEY_DHUK_SP:
|
||||
case SECURE_AES_KEY_DHUK_SN:
|
||||
case SECURE_AES_KEY_DHUK_NP:
|
||||
case SECURE_AES_KEY_DHUK_NN:
|
||||
return CRYP_KEYSEL_HW;
|
||||
case SECURE_AES_KEY_BHK:
|
||||
return CRYP_KEYSEL_SW;
|
||||
case SECURE_AES_KEY_XORK:
|
||||
case SECURE_AES_KEY_XORK_SP:
|
||||
case SECURE_AES_KEY_XORK_SN:
|
||||
case SECURE_AES_KEY_XORK_NP:
|
||||
case SECURE_AES_KEY_XORK_NN:
|
||||
return CRYP_KEYSEL_HSW;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static secbool is_key_supported(secure_aes_keysel_t key) {
|
||||
switch (key) {
|
||||
case SECURE_AES_KEY_DHUK_SP:
|
||||
case SECURE_AES_KEY_BHK:
|
||||
case SECURE_AES_KEY_XORK_SP:
|
||||
return sectrue;
|
||||
default:
|
||||
return secfalse;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SYSCALL_DISPATCH
|
||||
|
||||
__attribute__((section(".udata")))
|
||||
uint32_t saes_input[KERNEL_UNPRIVILEGED_SIZE / sizeof(uint32_t)];
|
||||
|
||||
__attribute__((section(".udata")))
|
||||
uint32_t saes_output[KERNEL_UNPRIVILEGED_SIZE / sizeof(uint32_t)];
|
||||
|
||||
__attribute__((section(".uflash"), used, naked, no_stack_protector)) uint32_t
|
||||
saes_invoke(void) {
|
||||
// reset the key loaded in SAES
|
||||
MODIFY_REG(SAES->CR, AES_CR_KEYSEL, CRYP_KEYSEL_NORMAL);
|
||||
|
||||
while (HAL_IS_BIT_SET(SAES->SR, CRYP_FLAG_BUSY)) {
|
||||
}
|
||||
while (HAL_IS_BIT_SET(SAES->ISR, CRYP_FLAG_RNGEIF)) {
|
||||
}
|
||||
|
||||
MODIFY_REG(SAES->CR,
|
||||
AES_CR_KMOD | AES_CR_DATATYPE | AES_CR_KEYSIZE | AES_CR_CHMOD |
|
||||
AES_CR_KEYSEL | AES_CR_KEYPROT,
|
||||
CRYP_KEYMODE_NORMAL | CRYP_NO_SWAP | CRYP_KEYSIZE_256B |
|
||||
CRYP_AES_ECB | CRYP_KEYSEL_HSW | CRYP_KEYPROT_DISABLE);
|
||||
|
||||
TAMP->BKP0R;
|
||||
TAMP->BKP1R;
|
||||
TAMP->BKP2R;
|
||||
TAMP->BKP3R;
|
||||
TAMP->BKP4R;
|
||||
TAMP->BKP5R;
|
||||
TAMP->BKP6R;
|
||||
TAMP->BKP7R;
|
||||
|
||||
#define CRYP_OPERATINGMODE_ENCRYPT 0x00000000U /*!< Encryption mode(Mode 1) */
|
||||
|
||||
/* Set the operating mode and normal key selection */
|
||||
MODIFY_REG(SAES->CR, AES_CR_MODE | AES_CR_KMOD,
|
||||
CRYP_OPERATINGMODE_ENCRYPT | CRYP_KEYMODE_NORMAL);
|
||||
|
||||
SAES->CR |= AES_CR_EN;
|
||||
|
||||
for (int j = 0; j < KERNEL_UNPRIVILEGED_SIZE / AES_BLOCK_SIZE; j++) {
|
||||
/* Write the input block in the IN FIFO */
|
||||
SAES->DINR = saes_input[j * 4 + 0];
|
||||
SAES->DINR = saes_input[j * 4 + 1];
|
||||
SAES->DINR = saes_input[j * 4 + 2];
|
||||
SAES->DINR = saes_input[j * 4 + 3];
|
||||
|
||||
while (HAL_IS_BIT_CLR(SAES->ISR, AES_ISR_CCF)) {
|
||||
}
|
||||
|
||||
/* Clear CCF Flag */
|
||||
SET_BIT(SAES->ICR, CRYP_CLEAR_CCF);
|
||||
|
||||
/* Read the output block from the output FIFO */
|
||||
for (int i = 0U; i < 4U; i++) {
|
||||
saes_output[j * 4 + i] = SAES->DOUTR;
|
||||
}
|
||||
}
|
||||
|
||||
SAES->CR &= ~AES_CR_EN;
|
||||
|
||||
// reset the key loaded in SAES
|
||||
MODIFY_REG(SAES->CR, AES_CR_KEYSEL, CRYP_KEYSEL_NORMAL);
|
||||
|
||||
register uint32_t r0 __asm__("r0") = sectrue;
|
||||
__asm__ volatile("svc %[svid]\n"
|
||||
:
|
||||
: [svid] "i"(SVC_CALLBACK_RETURN), "r"(r0)
|
||||
: "memory");
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern uint32_t sram2_u_start;
|
||||
extern uint32_t sram2_u_end;
|
||||
|
||||
secbool unpriv_encrypt(const uint8_t* input, size_t size, uint8_t* output,
|
||||
secure_aes_keysel_t key) {
|
||||
if (size != KERNEL_UNPRIVILEGED_SIZE) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
if (key != SECURE_AES_KEY_XORK_SN) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
NVIC_SetPriority(SVCall_IRQn, IRQ_PRI_HIGHEST);
|
||||
uint32_t basepri = __get_BASEPRI();
|
||||
__set_BASEPRI(1);
|
||||
|
||||
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SAES);
|
||||
|
||||
for (uint32_t* m = &sram2_u_start; m < &sram2_u_end; m++) {
|
||||
*m = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < KERNEL_UNPRIVILEGED_SIZE; i++) {
|
||||
((uint8_t*)saes_input)[i] = input[i];
|
||||
}
|
||||
|
||||
SAES->CR |= AES_CR_KEYSEL_0;
|
||||
|
||||
__HAL_RCC_SAES_CLK_DISABLE();
|
||||
__HAL_RCC_SAES_FORCE_RESET();
|
||||
__HAL_RCC_SAES_RELEASE_RESET();
|
||||
__HAL_RCC_SAES_CLK_ENABLE();
|
||||
|
||||
secbool retval = invoke_unpriv(saes_invoke);
|
||||
|
||||
__HAL_RCC_SAES_CLK_DISABLE();
|
||||
__HAL_RCC_SAES_FORCE_RESET();
|
||||
__HAL_RCC_SAES_RELEASE_RESET();
|
||||
__HAL_RCC_SAES_CLK_ENABLE();
|
||||
|
||||
for (int i = 0; i < KERNEL_UNPRIVILEGED_SIZE; i++) {
|
||||
output[i] = ((uint8_t*)saes_output)[i];
|
||||
}
|
||||
|
||||
for (int i = 0; i < KERNEL_UNPRIVILEGED_SIZE; i++) {
|
||||
((uint8_t*)saes_input)[i] = 0;
|
||||
((uint8_t*)saes_output)[i] = 0;
|
||||
}
|
||||
|
||||
for (uint32_t* m = &sram2_u_start; m < &sram2_u_end; m++) {
|
||||
*m = 0;
|
||||
}
|
||||
|
||||
mpu_reconfig(mpu_mode);
|
||||
|
||||
__set_BASEPRI(basepri);
|
||||
NVIC_SetPriority(SVCall_IRQn, IRQ_PRI_LOWEST);
|
||||
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
secbool secure_aes_ecb_encrypt_hw(const uint8_t* input, size_t size,
|
||||
uint8_t* output, secure_aes_keysel_t key) {
|
||||
#ifdef SYSCALL_DISPATCH
|
||||
if (key == SECURE_AES_KEY_XORK_SN) {
|
||||
return unpriv_encrypt(input, size, output, key);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (sectrue != is_key_supported(key)) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
CRYP_HandleTypeDef hcryp = {0};
|
||||
uint32_t iv[] = {0, 0, 0, 0};
|
||||
|
||||
@ -136,8 +290,28 @@ secbool secure_aes_ecb_encrypt_hw(const uint8_t* input, size_t size,
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
secbool secure_aes_init(void) {
|
||||
RCC_OscInitTypeDef osc_init_def = {0};
|
||||
osc_init_def.OscillatorType = RCC_OSCILLATORTYPE_SHSI;
|
||||
osc_init_def.SHSIState = RCC_SHSI_ON;
|
||||
|
||||
// Enable SHSI clock
|
||||
if (HAL_RCC_OscConfig(&osc_init_def) != HAL_OK) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
// Enable SAES peripheral clock
|
||||
__HAL_RCC_SAES_CLK_ENABLE();
|
||||
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
secbool secure_aes_ecb_decrypt_hw(const uint8_t* input, size_t size,
|
||||
uint8_t* output, secure_aes_keysel_t key) {
|
||||
if (sectrue != is_key_supported(key)) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
CRYP_HandleTypeDef hcryp = {0};
|
||||
uint32_t iv[] = {0, 0, 0, 0};
|
||||
|
||||
@ -202,4 +376,4 @@ secbool secure_aes_ecb_decrypt_hw(const uint8_t* input, size_t size,
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
#endif // KERNEL_MODE
|
||||
#endif
|
||||
|
@ -559,7 +559,7 @@ static void derive_kek_v4(const uint8_t *pin, size_t pin_len,
|
||||
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_KEY_XORK_SN),
|
||||
"secure_aes derive kek failed");
|
||||
memzero(pre_kek, sizeof(pre_kek));
|
||||
#else
|
||||
@ -617,7 +617,7 @@ static void stretch_pin(const uint8_t *pin, size_t pin_len,
|
||||
uint8_t stretched_pin_tmp[SHA256_DIGEST_LENGTH] = {0};
|
||||
pbkdf2_hmac_sha256_Final(&ctx, stretched_pin_tmp);
|
||||
ensure(secure_aes_ecb_encrypt_hw(stretched_pin_tmp, SHA256_DIGEST_LENGTH,
|
||||
stretched_pin, SECURE_AES_KEY_XORK),
|
||||
stretched_pin, SECURE_AES_KEY_XORK_SN),
|
||||
"secure_aes pin stretch failed");
|
||||
memzero(stretched_pin_tmp, sizeof(stretched_pin_tmp));
|
||||
#else
|
||||
|
Loading…
Reference in New Issue
Block a user