perf(core): optimize boot speed on U5 by using has processor to calculate image hashes, switches to sha256
[no changelog]pull/3474/head
parent
1ea7ca4149
commit
c3f84e2949
@ -0,0 +1,41 @@
|
||||
#ifndef LIB_IMAGE_HASH_H_
|
||||
#define LIB_IMAGE_HASH_H_
|
||||
|
||||
#include "model.h"
|
||||
#include TREZOR_BOARD
|
||||
|
||||
#ifdef IMAGE_HASH_SHA256
|
||||
#include "sha2.h"
|
||||
#define IMAGE_HASH_DIGEST_LENGTH SHA256_DIGEST_LENGTH
|
||||
#ifdef USE_HASH_PROCESSOR
|
||||
#include "hash_processor.h"
|
||||
#define IMAGE_HASH_CTX hash_sha265_context_t
|
||||
#define IMAGE_HASH_INIT(ctx) hash_processor_sha256_init(ctx)
|
||||
#define IMAGE_HASH_UPDATE(ctx, data, len) \
|
||||
hash_processor_sha256_update(ctx, data, len)
|
||||
#define IMAGE_HASH_FINAL(ctx, output) hash_processor_sha256_final(ctx, output)
|
||||
#define IMAGE_HASH_CALC(data, len, output) \
|
||||
hash_processor_sha256_calc(data, len, output)
|
||||
#else
|
||||
#define IMAGE_HASH_CTX SHA256_CTX
|
||||
#define IMAGE_HASH_INIT(ctx) sha256_Init(ctx)
|
||||
#define IMAGE_HASH_UPDATE(ctx, data, len) sha256_Update(ctx, data, len)
|
||||
#define IMAGE_HASH_FINAL(ctx, output) sha256_Final(ctx, output)
|
||||
#define IMAGE_HASH_CALC(data, len, output) sha256_Raw(data, len, output)
|
||||
#endif
|
||||
|
||||
#elif defined IMAGE_HASH_BLAKE2S
|
||||
#include "blake2s.h"
|
||||
#define IMAGE_HASH_DIGEST_LENGTH BLAKE2S_DIGEST_LENGTH
|
||||
#define IMAGE_HASH_CTX BLAKE2S_CTX
|
||||
#define IMAGE_HASH_INIT(ctx) blake2s_Init(ctx, BLAKE2S_DIGEST_LENGTH)
|
||||
#define IMAGE_HASH_UPDATE(ctx, data, len) blake2s_Update(ctx, data, len)
|
||||
#define IMAGE_HASH_FINAL(ctx, output) \
|
||||
blake2s_Final(ctx, output, BLAKE2S_DIGEST_LENGTH)
|
||||
#define IMAGE_HASH_CALC(data, len, output) \
|
||||
blake2s(data, len, output, BLAKE2S_DIGEST_LENGTH)
|
||||
#else
|
||||
#error "IMAGE_HASH_SHA256 or IMAGE_HASH_BLAKE2S must be defined"
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,33 @@
|
||||
#ifndef TREZORHAL_HASH_PROCESSOR_H_
|
||||
#define TREZORHAL_HASH_PROCESSOR_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define HASH_SHA256_BUFFER_SIZE 4
|
||||
|
||||
typedef struct {
|
||||
uint32_t length; /*!< nb bytes in buffer */
|
||||
uint8_t buffer[HASH_SHA256_BUFFER_SIZE]; /*!< data being processed */
|
||||
} hash_sha265_context_t;
|
||||
|
||||
// Initialize the hash processor
|
||||
void hash_processor_init(void);
|
||||
|
||||
// Calculate SHA256 hash of data
|
||||
// for best performance, data should be 32-bit aligned - as this allows DMA to
|
||||
// be used
|
||||
void hash_processor_sha256_calc(const uint8_t *data, uint32_t len,
|
||||
uint8_t *hash);
|
||||
|
||||
// Initialize the hash context
|
||||
// This serves for calculating hashes of multiple data blocks
|
||||
void hash_processor_sha256_init(hash_sha265_context_t *ctx);
|
||||
|
||||
// Feed the hash next chunk of data
|
||||
void hash_processor_sha256_update(hash_sha265_context_t *ctx,
|
||||
const uint8_t *data, uint32_t len);
|
||||
|
||||
// Finalize the hash calculation, retrieve the digest
|
||||
void hash_processor_sha256_final(hash_sha265_context_t *ctx, uint8_t *output);
|
||||
|
||||
#endif
|
@ -0,0 +1,132 @@
|
||||
#include "hash_processor.h"
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include STM32_HAL_H
|
||||
#include "irq.h"
|
||||
#include "memzero.h"
|
||||
#include "sha2.h"
|
||||
|
||||
HASH_HandleTypeDef hhash = {0};
|
||||
DMA_HandleTypeDef DMA_Handle = {0};
|
||||
|
||||
void hash_processor_init(void) {
|
||||
__HAL_RCC_HASH_CLK_ENABLE();
|
||||
__HAL_RCC_GPDMA1_CLK_ENABLE();
|
||||
|
||||
hhash.Init.DataType = HASH_DATATYPE_8B;
|
||||
hhash.hdmain = &DMA_Handle;
|
||||
HAL_HASH_Init(&hhash);
|
||||
|
||||
/* USER CODE END GPDMA1_Init 1 */
|
||||
DMA_Handle.Instance = GPDMA1_Channel12;
|
||||
DMA_Handle.Init.Request = GPDMA1_REQUEST_HASH_IN;
|
||||
DMA_Handle.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
|
||||
DMA_Handle.Init.Direction = DMA_MEMORY_TO_PERIPH;
|
||||
DMA_Handle.Init.SrcInc = DMA_SINC_INCREMENTED;
|
||||
DMA_Handle.Init.DestInc = DMA_DINC_FIXED;
|
||||
DMA_Handle.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_WORD;
|
||||
DMA_Handle.Init.DestDataWidth = DMA_DEST_DATAWIDTH_WORD;
|
||||
DMA_Handle.Init.Priority = DMA_LOW_PRIORITY_HIGH_WEIGHT;
|
||||
DMA_Handle.Init.SrcBurstLength = 1;
|
||||
DMA_Handle.Init.DestBurstLength = 4;
|
||||
DMA_Handle.Init.TransferAllocatedPort =
|
||||
DMA_SRC_ALLOCATED_PORT1 | DMA_DEST_ALLOCATED_PORT0;
|
||||
DMA_Handle.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
|
||||
DMA_Handle.Init.Mode = DMA_NORMAL;
|
||||
HAL_DMA_Init(&DMA_Handle);
|
||||
HAL_DMA_ConfigChannelAttributes(&DMA_Handle, DMA_CHANNEL_SEC |
|
||||
DMA_CHANNEL_SRC_SEC |
|
||||
DMA_CHANNEL_DEST_SEC);
|
||||
|
||||
DMA_Handle.Parent = &hhash;
|
||||
|
||||
HAL_NVIC_SetPriority(GPDMA1_Channel12_IRQn, IRQ_PRI_DMA, 0);
|
||||
HAL_NVIC_EnableIRQ(GPDMA1_Channel12_IRQn);
|
||||
}
|
||||
|
||||
void GPDMA1_Channel12_IRQHandler(void) { HAL_DMA_IRQHandler(&DMA_Handle); }
|
||||
|
||||
static void hash_processor_sha256_calc_dma(const uint8_t *data, uint32_t len,
|
||||
uint8_t *hash) {
|
||||
while (len > 0) {
|
||||
uint32_t chunk = len > 0x8000 ? 0x8000 : len;
|
||||
bool last = (len - chunk) <= 0;
|
||||
|
||||
__HAL_HASH_SET_MDMAT();
|
||||
|
||||
HAL_HASHEx_SHA256_Start_DMA(&hhash, (uint8_t *)data, chunk);
|
||||
while (HAL_HASH_GetState(&hhash) != HAL_HASH_STATE_READY)
|
||||
;
|
||||
|
||||
if (last) {
|
||||
HASH->STR |= HASH_STR_DCAL;
|
||||
HAL_HASHEx_SHA256_Finish(&hhash, hash, 1000);
|
||||
}
|
||||
data += chunk;
|
||||
len -= chunk;
|
||||
}
|
||||
}
|
||||
|
||||
void hash_processor_sha256_calc(const uint8_t *data, uint32_t len,
|
||||
uint8_t *hash) {
|
||||
if (((uint32_t)data & 0x3) == 0) {
|
||||
hash_processor_sha256_calc_dma(data, len, hash);
|
||||
} else {
|
||||
HAL_HASHEx_SHA256_Start(&hhash, (uint8_t *)data, len, hash, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
void hash_processor_sha256_init(hash_sha265_context_t *ctx) {
|
||||
memzero(ctx, sizeof(hash_sha265_context_t));
|
||||
}
|
||||
|
||||
void hash_processor_sha256_update(hash_sha265_context_t *ctx,
|
||||
const uint8_t *data, uint32_t len) {
|
||||
if (ctx->length > 0) {
|
||||
uint32_t chunk = HASH_SHA256_BUFFER_SIZE - ctx->length;
|
||||
if (chunk > len) {
|
||||
chunk = len;
|
||||
}
|
||||
memcpy(ctx->buffer + ctx->length, data, chunk);
|
||||
ctx->length += chunk;
|
||||
data += chunk;
|
||||
len -= chunk;
|
||||
if (ctx->length == HASH_SHA256_BUFFER_SIZE) {
|
||||
HAL_HASHEx_SHA256_Accmlt(&hhash, (uint8_t *)ctx->buffer,
|
||||
HASH_SHA256_BUFFER_SIZE);
|
||||
ctx->length = 0;
|
||||
memzero(ctx->buffer, HASH_SHA256_BUFFER_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t len_aligned = len & ~(HASH_SHA256_BUFFER_SIZE - 1);
|
||||
uint32_t len_rest = len & (HASH_SHA256_BUFFER_SIZE - 1);
|
||||
|
||||
while (len_aligned > 0) {
|
||||
uint32_t chunk = len_aligned > 0x8000 ? 0x8000 : len_aligned;
|
||||
HAL_HASHEx_SHA256_Accmlt(&hhash, (uint8_t *)data, chunk);
|
||||
data += chunk;
|
||||
len_aligned -= chunk;
|
||||
}
|
||||
|
||||
if (len_rest > 0) {
|
||||
memcpy(ctx->buffer, data, len_rest);
|
||||
ctx->length = len_rest;
|
||||
}
|
||||
}
|
||||
|
||||
void hash_processor_sha256_final(hash_sha265_context_t *ctx, uint8_t *output) {
|
||||
uint32_t tmp_out[SHA256_DIGEST_LENGTH / sizeof(uint32_t)] = {0};
|
||||
|
||||
if (ctx->length > 0) {
|
||||
memzero(ctx->buffer + ctx->length, HASH_SHA256_BUFFER_SIZE - ctx->length);
|
||||
HAL_HASHEx_SHA256_Accmlt_End(&hhash, (uint8_t *)ctx->buffer, ctx->length,
|
||||
(uint8_t *)tmp_out, 1000);
|
||||
ctx->length = 0;
|
||||
memzero(ctx->buffer, HASH_SHA256_BUFFER_SIZE);
|
||||
} else {
|
||||
HASH->STR |= HASH_STR_DCAL;
|
||||
HAL_HASHEx_SHA256_Finish(&hhash, (uint8_t *)tmp_out, 1000);
|
||||
}
|
||||
memcpy(output, tmp_out, SHA256_DIGEST_LENGTH);
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in new issue