Example for wolfCrypt PUF on STM32H5
parent
bfdda5612e
commit
87e913955f
|
|
@ -416,3 +416,5 @@ stsafe/wolfssl_stsafe_full_test
|
|||
|
||||
# uefi-library generated filesystem content
|
||||
uefi-library/efifs
|
||||
|
||||
puf/Build
|
||||
|
|
|
|||
11
README.md
11
README.md
|
|
@ -247,6 +247,17 @@ verifying/decrypting operations.
|
|||
Please see the [pkcs7/README.md](pkcs7/README.md) for further usage and details.
|
||||
|
||||
|
||||
<br />
|
||||
|
||||
#### PUF (SRAM Physically Unclonable Function)
|
||||
|
||||
This directory contains a bare-metal example demonstrating wolfCrypt's SRAM PUF
|
||||
support. It derives device-unique cryptographic keys from the power-on state of
|
||||
SRAM memory using a BCH(127,64,t=10) fuzzy extractor with HKDF key derivation.
|
||||
Tested on NUCLEO-H563ZI (Cortex-M33).
|
||||
|
||||
Please see the [puf/README.md](puf/README.md) for further usage and details.
|
||||
|
||||
<br />
|
||||
|
||||
#### PSK (Pre-Shared Keys)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,98 @@
|
|||
# Makefile for wolfCrypt SRAM PUF bare-metal example
|
||||
#
|
||||
# Target: Cortex-M (tested on NUCLEO-H563ZI)
|
||||
# Usage: make - build puf_example.elf and puf_example.hex
|
||||
# make clean - remove build artifacts
|
||||
# make PUF_TEST=0 - build for real hardware SRAM (no test mode)
|
||||
#
|
||||
# Copyright (C) 2006-2026 wolfSSL Inc.
|
||||
|
||||
# Toolchain
|
||||
TOOLCHAIN ?= arm-none-eabi-
|
||||
CC = $(TOOLCHAIN)gcc
|
||||
LD = $(TOOLCHAIN)gcc
|
||||
AR = $(TOOLCHAIN)ar
|
||||
OBJCOPY = $(TOOLCHAIN)objcopy
|
||||
OBJDUMP = $(TOOLCHAIN)objdump
|
||||
SIZE = $(TOOLCHAIN)size
|
||||
NM = $(TOOLCHAIN)nm
|
||||
|
||||
# wolfSSL root (relative to this directory)
|
||||
WOLFSSL_ROOT ?= ../../wolfssl
|
||||
|
||||
# Build output
|
||||
BUILD_DIR = ./Build
|
||||
BIN = puf_example
|
||||
|
||||
# Architecture
|
||||
ARCHFLAGS = -mcpu=cortex-m33 -mthumb -mabi=aapcs
|
||||
|
||||
# Compiler flags
|
||||
CFLAGS = $(ARCHFLAGS) -std=gnu99 -Wall -Os
|
||||
CFLAGS += -ffunction-sections -fdata-sections -fno-builtin
|
||||
CFLAGS += -DWOLFSSL_USER_SETTINGS
|
||||
CFLAGS += -I. -I$(WOLFSSL_ROOT)
|
||||
|
||||
# Linker flags
|
||||
LDFLAGS = $(ARCHFLAGS)
|
||||
LDFLAGS += --specs=nosys.specs --specs=nano.specs
|
||||
LDFLAGS += -Wl,--gc-sections
|
||||
LDFLAGS += -Wl,-Map=$(BUILD_DIR)/$(BIN).map
|
||||
LDFLAGS += -T./linker.ld
|
||||
|
||||
# Math lib
|
||||
LIBS = -lm
|
||||
|
||||
# Source files
|
||||
SRC_C = main.c
|
||||
SRC_C += startup.c
|
||||
SRC_C += stm32.c
|
||||
|
||||
# wolfCrypt sources needed for PUF
|
||||
SRC_C += $(WOLFSSL_ROOT)/wolfcrypt/src/puf.c
|
||||
SRC_C += $(WOLFSSL_ROOT)/wolfcrypt/src/sha256.c
|
||||
SRC_C += $(WOLFSSL_ROOT)/wolfcrypt/src/kdf.c
|
||||
SRC_C += $(WOLFSSL_ROOT)/wolfcrypt/src/hmac.c
|
||||
SRC_C += $(WOLFSSL_ROOT)/wolfcrypt/src/hash.c
|
||||
SRC_C += $(WOLFSSL_ROOT)/wolfcrypt/src/memory.c
|
||||
SRC_C += $(WOLFSSL_ROOT)/wolfcrypt/src/wc_port.c
|
||||
SRC_C += $(WOLFSSL_ROOT)/wolfcrypt/src/error.c
|
||||
SRC_C += $(WOLFSSL_ROOT)/wolfcrypt/src/misc.c
|
||||
SRC_C += $(WOLFSSL_ROOT)/wolfcrypt/src/logging.c
|
||||
SRC_C += $(WOLFSSL_ROOT)/wolfcrypt/src/random.c
|
||||
SRC_C += $(WOLFSSL_ROOT)/wolfcrypt/src/sp_int.c
|
||||
SRC_C += $(WOLFSSL_ROOT)/wolfcrypt/src/sha3.c
|
||||
|
||||
# Object files
|
||||
FILENAMES_C = $(notdir $(SRC_C))
|
||||
OBJS_C = $(addprefix $(BUILD_DIR)/, $(FILENAMES_C:.c=.o))
|
||||
vpath %.c $(dir $(SRC_C))
|
||||
|
||||
# Targets
|
||||
.PHONY: all clean
|
||||
|
||||
all: $(BUILD_DIR) $(BUILD_DIR)/$(BIN).hex
|
||||
@echo ""
|
||||
$(SIZE) $(BUILD_DIR)/$(BIN).elf
|
||||
|
||||
$(BUILD_DIR):
|
||||
mkdir -p $(BUILD_DIR)
|
||||
|
||||
$(BUILD_DIR)/%.o: %.c
|
||||
@echo "Compiling: $(notdir $<)"
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
$(BUILD_DIR)/$(BIN).elf: $(OBJS_C)
|
||||
@echo "Linking: $(notdir $@)"
|
||||
$(LD) $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||
@echo ""
|
||||
$(NM) -n $@ > $(BUILD_DIR)/$(BIN).sym
|
||||
$(OBJDUMP) -S $@ > $(BUILD_DIR)/$(BIN).disasm
|
||||
|
||||
$(BUILD_DIR)/$(BIN).hex: $(BUILD_DIR)/$(BIN).elf
|
||||
@echo "Generating HEX: $(notdir $@)"
|
||||
$(OBJCOPY) -O ihex $< $@
|
||||
|
||||
clean:
|
||||
rm -f $(BUILD_DIR)/*.elf $(BUILD_DIR)/*.hex $(BUILD_DIR)/*.map
|
||||
rm -f $(BUILD_DIR)/*.o $(BUILD_DIR)/*.sym $(BUILD_DIR)/*.disasm
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
# wolfCrypt SRAM PUF Example
|
||||
|
||||
Bare-metal example demonstrating SRAM PUF (Physically Unclonable Function)
|
||||
on Cortex-M targets (tested on NUCLEO-H563ZI).
|
||||
|
||||
## Overview
|
||||
|
||||
SRAM PUF exploits the random power-on state of SRAM memory cells to derive
|
||||
device-unique cryptographic keys. Each chip has a unique SRAM "fingerprint"
|
||||
caused by manufacturing variations.
|
||||
|
||||
This example demonstrates:
|
||||
|
||||
1. **Enrollment** - Read raw SRAM, generate helper data using BCH(127,64,t=10)
|
||||
error-correcting codes
|
||||
2. **Reconstruction** - Re-read (noisy) SRAM, use helper data to recover the
|
||||
same stable bits despite bit flips (corrects up to 10 per 127-bit codeword)
|
||||
3. **Key derivation** - Use HKDF-SHA256 to derive a 256-bit cryptographic key
|
||||
4. **Device identity** - SHA-256 hash of stable bits serves as a unique device ID
|
||||
|
||||
## Building
|
||||
|
||||
### Requirements
|
||||
|
||||
- `arm-none-eabi-gcc` toolchain
|
||||
|
||||
### Test Mode (default)
|
||||
|
||||
Uses synthetic SRAM data -- runs on any target, no real hardware needed:
|
||||
|
||||
```bash
|
||||
make
|
||||
```
|
||||
|
||||
### Real Hardware Mode
|
||||
|
||||
For actual SRAM PUF on hardware, edit `user_settings.h` and comment out
|
||||
`WOLFSSL_PUF_TEST`, then build:
|
||||
|
||||
```bash
|
||||
make
|
||||
```
|
||||
|
||||
### Output
|
||||
|
||||
Build output is placed in `./Build/`:
|
||||
- `puf_example.elf` - Loadable ELF binary
|
||||
- `puf_example.hex` - Intel HEX for flash programmers
|
||||
|
||||
## Flashing
|
||||
|
||||
### OpenOCD (NUCLEO-H563ZI)
|
||||
|
||||
```bash
|
||||
openocd -f interface/stlink.cfg -f target/stm32h5x.cfg \
|
||||
-c "program Build/puf_example.elf verify reset exit"
|
||||
```
|
||||
|
||||
When multiple ST-Links are connected, specify the serial number:
|
||||
|
||||
```bash
|
||||
openocd -f interface/stlink.cfg \
|
||||
-c "adapter serial <YOUR_SERIAL>" \
|
||||
-f target/stm32h5x.cfg \
|
||||
-c "program Build/puf_example.elf verify reset exit"
|
||||
```
|
||||
|
||||
## UART Output
|
||||
|
||||
Connect to the board's UART (typically 115200 baud) to see output:
|
||||
|
||||
```
|
||||
--- wolfCrypt SRAM PUF Example ---
|
||||
|
||||
PUF initialized.
|
||||
Mode: TEST (synthetic SRAM data)
|
||||
|
||||
Enrollment complete.
|
||||
Identity (enrollment): 3ad99904f92897bad1a21bc9cbc3ab8f2dc4bc40dfe6e161c741f98ef8dd7e01
|
||||
Derived key (enrollment): aa8573f70a3253ca567500bdcd610face6a140e5fc68047e02d3f13958dcc480
|
||||
|
||||
--- Simulating power cycle (noisy SRAM) ---
|
||||
|
||||
Reconstruction complete (BCH corrected noisy bits).
|
||||
Identity (reconstructed): 3ad99904f92897bad1a21bc9cbc3ab8f2dc4bc40dfe6e161c741f98ef8dd7e01
|
||||
PASS: Identity matches after reconstruction.
|
||||
Derived key (reconstructed): aa8573f70a3253ca567500bdcd610face6a140e5fc68047e02d3f13958dcc480
|
||||
PASS: Derived key matches after reconstruction.
|
||||
|
||||
--- PUF example complete ---
|
||||
```
|
||||
|
||||
## Customizing for Your MCU
|
||||
|
||||
### Linker Script
|
||||
|
||||
Edit `linker.ld` to match your MCU's memory map:
|
||||
|
||||
```ld
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K /* your flash size */
|
||||
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 636K /* total - PUF_RAM */
|
||||
PUF_RAM (rw) : ORIGIN = 0x2009F000, LENGTH = 4K /* end of SRAM */
|
||||
}
|
||||
```
|
||||
|
||||
The `PUF_RAM` region must be at the end of SRAM and marked `NOLOAD` so the
|
||||
startup code does not zero it.
|
||||
|
||||
### Architecture
|
||||
|
||||
Edit the `ARCHFLAGS` in `Makefile`:
|
||||
|
||||
```makefile
|
||||
ARCHFLAGS = -mcpu=cortex-m33 -mthumb
|
||||
```
|
||||
|
||||
## API Usage
|
||||
|
||||
```c
|
||||
wc_PufCtx ctx;
|
||||
uint8_t helperData[WC_PUF_HELPER_BYTES];
|
||||
uint8_t key[WC_PUF_KEY_SZ];
|
||||
|
||||
/* First boot: Enroll */
|
||||
wc_PufInit(&ctx);
|
||||
wc_PufReadSram(&ctx, sram_addr, sram_size);
|
||||
wc_PufEnroll(&ctx);
|
||||
memcpy(helperData, ctx.helperData, WC_PUF_HELPER_BYTES);
|
||||
/* Store helperData to flash/NVM (it is NOT secret) */
|
||||
|
||||
/* Subsequent boots: Reconstruct */
|
||||
wc_PufInit(&ctx);
|
||||
wc_PufReadSram(&ctx, sram_addr, sram_size);
|
||||
wc_PufReconstruct(&ctx, helperData, WC_PUF_HELPER_BYTES);
|
||||
wc_PufDeriveKey(&ctx, info, infoSz, key, sizeof(key));
|
||||
|
||||
/* Always zeroize when done */
|
||||
wc_PufZeroize(&ctx);
|
||||
```
|
||||
|
||||
## Security Notes
|
||||
|
||||
- **Helper data is public** - It does not reveal the key. Safe to store
|
||||
unencrypted in flash or transmit over the network.
|
||||
- **SRAM must not be accessed before PUF read** - Any read or write to the
|
||||
PUF SRAM region before `wc_PufReadSram()` will corrupt the power-on entropy.
|
||||
- **Production RNG** - Replace the dummy `my_rng_seed_gen()` with your
|
||||
MCU's hardware RNG (e.g., STM32 RNG peripheral).
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
/* linker.ld
|
||||
*
|
||||
* Linker script for bare-metal Cortex-M33 with PUF SRAM region.
|
||||
* Default: NUCLEO-H563ZI (STM32H563ZI)
|
||||
*
|
||||
* Uses STM32-standard symbol names for compatibility with
|
||||
* startup_stm32h563zitx.s from STM32CubeH5.
|
||||
*
|
||||
* Copyright (C) 2006-2026 wolfSSL Inc.
|
||||
*/
|
||||
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
_estack = ORIGIN(RAM) + LENGTH(RAM);
|
||||
_Min_Heap_Size = 0x400;
|
||||
_Min_Stack_Size = 0x2000;
|
||||
|
||||
MEMORY
|
||||
{
|
||||
/* STM32H563ZI: 2MB flash, 640KB SRAM */
|
||||
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K
|
||||
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 636K
|
||||
/* Reserve 4K at end of SRAM for PUF (not touched by .bss clear) */
|
||||
PUF_RAM (rw) : ORIGIN = 0x2009F000, LENGTH = 4K
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.isr_vector :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.isr_vector))
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
.text :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.text)
|
||||
*(.text*)
|
||||
*(.glue_7)
|
||||
*(.glue_7t)
|
||||
*(.eh_frame)
|
||||
KEEP(*(.init))
|
||||
KEEP(*(.fini))
|
||||
. = ALIGN(4);
|
||||
_etext = .;
|
||||
} > FLASH
|
||||
|
||||
.rodata :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.rodata)
|
||||
*(.rodata*)
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > FLASH
|
||||
|
||||
.ARM :
|
||||
{
|
||||
__exidx_start = .;
|
||||
*(.ARM.exidx*)
|
||||
__exidx_end = .;
|
||||
} > FLASH
|
||||
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP(*(.preinit_array*))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
} > FLASH
|
||||
|
||||
.init_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP(*(SORT(.init_array.*)))
|
||||
KEEP(*(.init_array*))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
} > FLASH
|
||||
|
||||
.fini_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP(*(SORT(.fini_array.*)))
|
||||
KEEP(*(.fini_array*))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
} > FLASH
|
||||
|
||||
_sidata = LOADADDR(.data);
|
||||
|
||||
.data :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_sdata = .;
|
||||
*(.data)
|
||||
*(.data*)
|
||||
. = ALIGN(4);
|
||||
_edata = .;
|
||||
} > RAM AT> FLASH
|
||||
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_sbss = .;
|
||||
__bss_start__ = _sbss;
|
||||
*(.bss)
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
_ebss = .;
|
||||
__bss_end__ = _ebss;
|
||||
} > RAM
|
||||
|
||||
._user_heap_stack :
|
||||
{
|
||||
. = ALIGN(8);
|
||||
PROVIDE(end = .);
|
||||
. = . + _Min_Heap_Size;
|
||||
. = . + _Min_Stack_Size;
|
||||
. = ALIGN(8);
|
||||
} > RAM
|
||||
|
||||
/* PUF SRAM section: NOLOAD prevents startup code from zeroing.
|
||||
* The raw power-on state of these bytes is the PUF source. */
|
||||
.puf_sram (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_puf_sram_start = .;
|
||||
KEEP(*(.puf_sram))
|
||||
KEEP(*(.puf_sram.*))
|
||||
_puf_sram_end = .;
|
||||
} > PUF_RAM
|
||||
}
|
||||
|
|
@ -0,0 +1,275 @@
|
|||
/* main.c
|
||||
*
|
||||
* Bare-metal SRAM PUF example for Cortex-M.
|
||||
*
|
||||
* Platform-portable PUF demonstration: enrollment, reconstruction,
|
||||
* key derivation, and device identity. HAL-specific code (UART, RNG)
|
||||
* is in a separate file (e.g., stm32.c).
|
||||
*
|
||||
* Supports both test mode (synthetic SRAM data) and real hardware SRAM PUF.
|
||||
*
|
||||
* Copyright (C) 2006-2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfSSL.
|
||||
*
|
||||
* wolfSSL is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfSSL is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
|
||||
#include <wolfssl/wolfcrypt/settings.h>
|
||||
#include <wolfssl/wolfcrypt/puf.h>
|
||||
#include <wolfssl/wolfcrypt/error-crypt.h>
|
||||
#include <wolfssl/wolfcrypt/wc_port.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Platform HAL init (implemented in stm32.c or other target file) */
|
||||
extern void hal_init(void);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* PUF SRAM region (real hardware path) */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef WOLFSSL_PUF_TEST
|
||||
/* This buffer is placed in the .puf_sram linker section (NOLOAD).
|
||||
* The startup code must NOT zero this region - the raw power-on SRAM
|
||||
* state is the PUF entropy source. */
|
||||
__attribute__((section(".puf_sram")))
|
||||
static volatile uint8_t puf_sram_region[WC_PUF_RAW_BYTES];
|
||||
#endif
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Helper: print hex buffer */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static void print_hex(const char* label, const uint8_t* data, uint32_t len)
|
||||
{
|
||||
uint32_t i;
|
||||
printf("%s: ", label);
|
||||
for (i = 0; i < len; i++)
|
||||
printf("%02x", data[i]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Main PUF demonstration */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int main(void)
|
||||
{
|
||||
wc_PufCtx ctx;
|
||||
int ret;
|
||||
uint8_t identity[WC_PUF_ID_SZ];
|
||||
uint8_t key[WC_PUF_KEY_SZ];
|
||||
uint8_t helperData[WC_PUF_HELPER_BYTES];
|
||||
const uint8_t info[] = "puf-example-key";
|
||||
|
||||
/* Initialize platform HAL (UART, clocks, etc.) */
|
||||
hal_init();
|
||||
|
||||
printf("\n--- wolfCrypt SRAM PUF Example ---\n\n");
|
||||
|
||||
/* Initialize wolfCrypt */
|
||||
ret = wolfCrypt_Init();
|
||||
if (ret != 0) {
|
||||
printf("ERROR: wolfCrypt_Init failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Step 1: Initialize PUF context */
|
||||
ret = wc_PufInit(&ctx);
|
||||
if (ret != 0) {
|
||||
printf("ERROR: wc_PufInit failed: %d\n", ret);
|
||||
goto cleanup;
|
||||
}
|
||||
printf("PUF initialized.\n");
|
||||
|
||||
#ifdef WOLFSSL_PUF_TEST
|
||||
/* ================================================================== */
|
||||
/* TEST MODE: Use synthetic SRAM data */
|
||||
/* ================================================================== */
|
||||
{
|
||||
/* Synthetic SRAM pattern for testing (deterministic) */
|
||||
uint8_t testSram[WC_PUF_RAW_BYTES];
|
||||
uint8_t noisySram[WC_PUF_RAW_BYTES];
|
||||
uint8_t identity2[WC_PUF_ID_SZ];
|
||||
uint8_t key2[WC_PUF_KEY_SZ];
|
||||
uint32_t i;
|
||||
|
||||
printf("Mode: TEST (synthetic SRAM data)\n\n");
|
||||
|
||||
/* Generate deterministic test pattern */
|
||||
for (i = 0; i < WC_PUF_RAW_BYTES; i++)
|
||||
testSram[i] = (uint8_t)((i * 37 + 13) ^ (i >> 2));
|
||||
|
||||
/* Step 2: Load test SRAM data */
|
||||
ret = wc_PufSetTestData(&ctx, testSram, sizeof(testSram));
|
||||
if (ret != 0) {
|
||||
printf("ERROR: wc_PufSetTestData failed: %d\n", ret);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Step 3: Enroll - generates helper data from SRAM pattern */
|
||||
ret = wc_PufEnroll(&ctx);
|
||||
if (ret != 0) {
|
||||
printf("ERROR: wc_PufEnroll failed: %d\n", ret);
|
||||
goto cleanup;
|
||||
}
|
||||
printf("Enrollment complete.\n");
|
||||
|
||||
/* Save helper data (in production, store to flash/NVM) */
|
||||
memcpy(helperData, ctx.helperData, WC_PUF_HELPER_BYTES);
|
||||
|
||||
/* Get device identity */
|
||||
ret = wc_PufGetIdentity(&ctx, identity, sizeof(identity));
|
||||
if (ret != 0) {
|
||||
printf("ERROR: wc_PufGetIdentity failed: %d\n", ret);
|
||||
goto cleanup;
|
||||
}
|
||||
print_hex("Identity (enrollment)", identity, WC_PUF_ID_SZ);
|
||||
|
||||
/* Derive a key */
|
||||
ret = wc_PufDeriveKey(&ctx, info, sizeof(info), key, sizeof(key));
|
||||
if (ret != 0) {
|
||||
printf("ERROR: wc_PufDeriveKey failed: %d\n", ret);
|
||||
goto cleanup;
|
||||
}
|
||||
print_hex("Derived key (enrollment)", key, WC_PUF_KEY_SZ);
|
||||
|
||||
/* ---- Simulate power cycle with noisy SRAM ---- */
|
||||
printf("\n--- Simulating power cycle (noisy SRAM) ---\n\n");
|
||||
|
||||
/* Create noisy copy: flip a few bits per 128-bit block */
|
||||
memcpy(noisySram, testSram, WC_PUF_RAW_BYTES);
|
||||
for (i = 0; i < 16; i++) {
|
||||
/* Flip 2 bits in each 16-byte (128-bit) block */
|
||||
noisySram[i * 16 + 3] ^= 0x04;
|
||||
noisySram[i * 16 + 11] ^= 0x20;
|
||||
}
|
||||
|
||||
/* Re-initialize and load noisy SRAM */
|
||||
ret = wc_PufInit(&ctx);
|
||||
if (ret != 0) {
|
||||
printf("ERROR: wc_PufInit failed: %d\n", ret);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = wc_PufSetTestData(&ctx, noisySram, sizeof(noisySram));
|
||||
if (ret != 0) {
|
||||
printf("ERROR: wc_PufSetTestData failed: %d\n", ret);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Step 4: Reconstruct stable bits using helper data */
|
||||
ret = wc_PufReconstruct(&ctx, helperData, WC_PUF_HELPER_BYTES);
|
||||
if (ret != 0) {
|
||||
printf("ERROR: wc_PufReconstruct failed: %d\n", ret);
|
||||
goto cleanup;
|
||||
}
|
||||
printf("Reconstruction complete (BCH corrected noisy bits).\n");
|
||||
|
||||
/* Verify identity matches */
|
||||
ret = wc_PufGetIdentity(&ctx, identity2, sizeof(identity2));
|
||||
if (ret != 0) {
|
||||
printf("ERROR: wc_PufGetIdentity failed: %d\n", ret);
|
||||
goto cleanup;
|
||||
}
|
||||
print_hex("Identity (reconstructed)", identity2, WC_PUF_ID_SZ);
|
||||
|
||||
if (memcmp(identity, identity2, WC_PUF_ID_SZ) == 0) {
|
||||
printf("PASS: Identity matches after reconstruction.\n");
|
||||
}
|
||||
else {
|
||||
printf("FAIL: Identity mismatch!\n");
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Verify derived key matches */
|
||||
ret = wc_PufDeriveKey(&ctx, info, sizeof(info), key2, sizeof(key2));
|
||||
if (ret != 0) {
|
||||
printf("ERROR: wc_PufDeriveKey failed: %d\n", ret);
|
||||
goto cleanup;
|
||||
}
|
||||
print_hex("Derived key (reconstructed)", key2, WC_PUF_KEY_SZ);
|
||||
|
||||
if (memcmp(key, key2, WC_PUF_KEY_SZ) == 0) {
|
||||
printf("PASS: Derived key matches after reconstruction.\n");
|
||||
}
|
||||
else {
|
||||
printf("FAIL: Derived key mismatch!\n");
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* ================================================================== */
|
||||
/* REAL HARDWARE: Read actual SRAM PUF */
|
||||
/* ================================================================== */
|
||||
printf("Mode: HARDWARE (real SRAM PUF)\n\n");
|
||||
|
||||
/* Step 2: Read raw SRAM (must be done before any other SRAM access) */
|
||||
ret = wc_PufReadSram(&ctx, (const uint8_t*)puf_sram_region,
|
||||
sizeof(puf_sram_region));
|
||||
if (ret != 0) {
|
||||
printf("ERROR: wc_PufReadSram failed: %d\n", ret);
|
||||
goto cleanup;
|
||||
}
|
||||
printf("SRAM read complete (%d bytes).\n", (int)sizeof(puf_sram_region));
|
||||
|
||||
/* Step 3: Enroll (first boot only - save helper data to flash/NVM) */
|
||||
ret = wc_PufEnroll(&ctx);
|
||||
if (ret != 0) {
|
||||
printf("ERROR: wc_PufEnroll failed: %d\n", ret);
|
||||
goto cleanup;
|
||||
}
|
||||
printf("Enrollment complete.\n");
|
||||
|
||||
/* Save helper data for future reconstructions */
|
||||
memcpy(helperData, ctx.helperData, WC_PUF_HELPER_BYTES);
|
||||
print_hex("Helper data (store to NVM)", helperData, WC_PUF_HELPER_BYTES);
|
||||
|
||||
/* Get device identity */
|
||||
ret = wc_PufGetIdentity(&ctx, identity, sizeof(identity));
|
||||
if (ret != 0) {
|
||||
printf("ERROR: wc_PufGetIdentity failed: %d\n", ret);
|
||||
goto cleanup;
|
||||
}
|
||||
print_hex("Device identity", identity, WC_PUF_ID_SZ);
|
||||
|
||||
/* Derive a key */
|
||||
ret = wc_PufDeriveKey(&ctx, info, sizeof(info), key, sizeof(key));
|
||||
if (ret != 0) {
|
||||
printf("ERROR: wc_PufDeriveKey failed: %d\n", ret);
|
||||
goto cleanup;
|
||||
}
|
||||
print_hex("Derived key", key, WC_PUF_KEY_SZ);
|
||||
|
||||
/* Note: On subsequent boots, use wc_PufReconstruct() with the stored
|
||||
* helper data instead of wc_PufEnroll(). The BCH error correction
|
||||
* (t=10, corrects up to 10 bit flips per 127-bit codeword) will
|
||||
* recover the same stable bits even with noisy SRAM. */
|
||||
#endif /* WOLFSSL_PUF_TEST */
|
||||
|
||||
printf("\n--- PUF example complete ---\n");
|
||||
|
||||
cleanup:
|
||||
/* Securely zeroize all PUF secrets */
|
||||
wc_PufZeroize(&ctx);
|
||||
wolfCrypt_Cleanup();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
/* startup.c
|
||||
*
|
||||
* Minimal Cortex-M startup for PUF example.
|
||||
* Provides vector table, Reset_Handler, and SystemInit.
|
||||
*
|
||||
* Copyright (C) 2006-2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfSSL.
|
||||
*
|
||||
* wolfSSL is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfSSL is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Linker-provided symbols (STM32-standard names) */
|
||||
extern uint32_t _estack;
|
||||
extern uint32_t _sidata, _sdata, _edata;
|
||||
extern uint32_t _sbss, _ebss;
|
||||
extern void __libc_init_array(void);
|
||||
extern int main(void);
|
||||
|
||||
/* Forward declarations */
|
||||
void Reset_Handler(void);
|
||||
void Default_Handler(void);
|
||||
void SystemInit(void);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* SystemInit - minimal clock setup */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void SystemInit(void)
|
||||
{
|
||||
/* Set VTOR to flash base */
|
||||
*(volatile uint32_t *)0xE000ED08 = 0x08000000;
|
||||
/* Default HSI clock (64 MHz) is sufficient for this example */
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Reset Handler */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void __attribute__((naked)) Reset_Handler(void)
|
||||
{
|
||||
__asm volatile (
|
||||
"ldr r0, =_estack \n"
|
||||
"mov sp, r0 \n"
|
||||
"bl SystemInit \n"
|
||||
|
||||
/* Copy .data from flash to SRAM */
|
||||
"ldr r0, =_sdata \n"
|
||||
"ldr r1, =_edata \n"
|
||||
"ldr r2, =_sidata \n"
|
||||
"movs r3, #0 \n"
|
||||
"b .Ldata_check \n"
|
||||
".Ldata_copy: \n"
|
||||
"ldr r4, [r2, r3] \n"
|
||||
"str r4, [r0, r3] \n"
|
||||
"adds r3, r3, #4 \n"
|
||||
".Ldata_check: \n"
|
||||
"adds r4, r0, r3 \n"
|
||||
"cmp r4, r1 \n"
|
||||
"bcc .Ldata_copy \n"
|
||||
|
||||
/* Zero .bss */
|
||||
"ldr r2, =_sbss \n"
|
||||
"ldr r4, =_ebss \n"
|
||||
"movs r3, #0 \n"
|
||||
"b .Lbss_check \n"
|
||||
".Lbss_zero: \n"
|
||||
"str r3, [r2] \n"
|
||||
"adds r2, r2, #4 \n"
|
||||
".Lbss_check: \n"
|
||||
"cmp r2, r4 \n"
|
||||
"bcc .Lbss_zero \n"
|
||||
|
||||
/* Call static constructors, then main */
|
||||
"bl __libc_init_array \n"
|
||||
"bl main \n"
|
||||
".Lhang: \n"
|
||||
"b .Lhang \n"
|
||||
);
|
||||
}
|
||||
|
||||
void Default_Handler(void)
|
||||
{
|
||||
while (1) { }
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Vector table */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* Weak aliases so the application can override individual handlers */
|
||||
void __attribute__((weak, alias("Default_Handler"))) NMI_Handler(void);
|
||||
void __attribute__((weak, alias("Default_Handler"))) HardFault_Handler(void);
|
||||
void __attribute__((weak, alias("Default_Handler"))) MemManage_Handler(void);
|
||||
void __attribute__((weak, alias("Default_Handler"))) BusFault_Handler(void);
|
||||
void __attribute__((weak, alias("Default_Handler"))) UsageFault_Handler(void);
|
||||
void __attribute__((weak, alias("Default_Handler"))) SecureFault_Handler(void);
|
||||
void __attribute__((weak, alias("Default_Handler"))) SVC_Handler(void);
|
||||
void __attribute__((weak, alias("Default_Handler"))) DebugMon_Handler(void);
|
||||
void __attribute__((weak, alias("Default_Handler"))) PendSV_Handler(void);
|
||||
void __attribute__((weak, alias("Default_Handler"))) SysTick_Handler(void);
|
||||
|
||||
typedef void (*vector_fn)(void);
|
||||
|
||||
const vector_fn __isr_vector[] __attribute__((section(".isr_vector"), used)) = {
|
||||
(vector_fn)(uintptr_t)&_estack, /* Initial SP */
|
||||
Reset_Handler, /* Reset */
|
||||
NMI_Handler, /* NMI */
|
||||
HardFault_Handler, /* Hard Fault */
|
||||
MemManage_Handler, /* MPU Fault */
|
||||
BusFault_Handler, /* Bus Fault */
|
||||
UsageFault_Handler, /* Usage Fault */
|
||||
SecureFault_Handler, /* Secure Fault (M33) */
|
||||
0, 0, 0, /* Reserved */
|
||||
SVC_Handler, /* SVCall */
|
||||
DebugMon_Handler, /* Debug Monitor */
|
||||
0, /* Reserved */
|
||||
PendSV_Handler, /* PendSV */
|
||||
SysTick_Handler, /* SysTick */
|
||||
/* Peripheral IRQs default to Default_Handler via unused slots */
|
||||
};
|
||||
|
|
@ -0,0 +1,244 @@
|
|||
/* stm32.c
|
||||
*
|
||||
* STM32H5 HAL support for PUF example (tested on NUCLEO-H563ZI).
|
||||
* Provides USART3 init/output, printf retarget, RNG stub, and time stub.
|
||||
*
|
||||
* To port to a different MCU, replace this file with your platform's
|
||||
* UART and RNG implementation. The interface is:
|
||||
* void hal_init(void) - called once at startup before printf
|
||||
* int my_rng_seed_gen(uint8_t* output, uint32_t sz) - RNG seed
|
||||
* unsigned long my_time(unsigned long* timer) - monotonic time
|
||||
*
|
||||
* Copyright (C) 2006-2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfSSL.
|
||||
*
|
||||
* wolfSSL is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfSSL is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* STM32H5 USART3 (ST-LINK VCP) bare-metal driver */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* STM32H563 register bases.
|
||||
* TZEN=0: use non-secure aliases (0x4xxx).
|
||||
* TZEN=1: use secure aliases (0x5xxx). */
|
||||
#ifdef STM32H5_TZEN
|
||||
#define RCC_BASE 0x54020C00u
|
||||
#define GPIOD_BASE 0x52020C00u
|
||||
#define USART3_BASE 0x50004800u
|
||||
#else
|
||||
#define RCC_BASE 0x44020C00u
|
||||
#define GPIOD_BASE 0x42020C00u
|
||||
#define USART3_BASE 0x40004800u
|
||||
#endif
|
||||
|
||||
#define RCC_AHB2ENR (*(volatile uint32_t *)(RCC_BASE + 0x8Cu))
|
||||
#define RCC_APB1ENR (*(volatile uint32_t *)(RCC_BASE + 0x9Cu))
|
||||
|
||||
/* GPIO registers */
|
||||
#define GPIO_MODER(b) (*(volatile uint32_t *)((b) + 0x00u))
|
||||
#define GPIO_OSPEEDR(b) (*(volatile uint32_t *)((b) + 0x08u))
|
||||
#define GPIO_AFRH(b) (*(volatile uint32_t *)((b) + 0x24u))
|
||||
|
||||
/* USART3 registers */
|
||||
#define USART3_CR1 (*(volatile uint32_t *)(USART3_BASE + 0x00u))
|
||||
#define USART3_CR2 (*(volatile uint32_t *)(USART3_BASE + 0x04u))
|
||||
#define USART3_CR3 (*(volatile uint32_t *)(USART3_BASE + 0x08u))
|
||||
#define USART3_BRR (*(volatile uint32_t *)(USART3_BASE + 0x0Cu))
|
||||
#define USART3_ISR (*(volatile uint32_t *)(USART3_BASE + 0x1Cu))
|
||||
#define USART3_TDR (*(volatile uint32_t *)(USART3_BASE + 0x28u))
|
||||
#define USART3_PRESC (*(volatile uint32_t *)(USART3_BASE + 0x2Cu))
|
||||
|
||||
static void delay(volatile uint32_t n)
|
||||
{
|
||||
while (n--) { }
|
||||
}
|
||||
|
||||
static void uart_init(void)
|
||||
{
|
||||
uint32_t moder, afr;
|
||||
|
||||
/* Enable GPIOD clock */
|
||||
RCC_AHB2ENR |= (1u << 3);
|
||||
/* Enable USART3 clock (APB1LENR bit 18) */
|
||||
RCC_APB1ENR |= (1u << 18);
|
||||
delay(100);
|
||||
|
||||
/* Configure PD8 (TX) as AF7, push-pull, high speed */
|
||||
moder = GPIO_MODER(GPIOD_BASE);
|
||||
moder &= ~(3u << 16);
|
||||
moder |= (2u << 16); /* Alternate function */
|
||||
GPIO_MODER(GPIOD_BASE) = moder;
|
||||
GPIO_OSPEEDR(GPIOD_BASE) |= (3u << 16); /* High speed for PD8 */
|
||||
afr = GPIO_AFRH(GPIOD_BASE);
|
||||
afr &= ~(0xFu << 0);
|
||||
afr |= (7u << 0); /* AF7 = USART3 */
|
||||
GPIO_AFRH(GPIOD_BASE) = afr;
|
||||
|
||||
/* Configure USART3: 115200 baud at default 32 MHz PCLK1 */
|
||||
USART3_CR1 = 0;
|
||||
USART3_CR2 = 0;
|
||||
USART3_CR3 = 0;
|
||||
USART3_PRESC = 0;
|
||||
USART3_BRR = 32000000u / 115200u; /* ~278 */
|
||||
USART3_CR1 = (1u << 3); /* TE */
|
||||
delay(10);
|
||||
USART3_CR1 |= (1u << 0); /* UE */
|
||||
delay(100);
|
||||
}
|
||||
|
||||
static void uart_putc(char c)
|
||||
{
|
||||
while ((USART3_ISR & (1u << 7)) == 0) { }
|
||||
USART3_TDR = (uint32_t)c;
|
||||
}
|
||||
|
||||
/* Retarget _write for printf via USART3 */
|
||||
int _write(int fd, const char *buf, int len)
|
||||
{
|
||||
int i;
|
||||
(void)fd;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (buf[i] == '\n')
|
||||
uart_putc('\r');
|
||||
uart_putc(buf[i]);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* STM32H5 Hardware RNG (TRNG) driver */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* RCC clock control */
|
||||
#define RCC_CR (*(volatile uint32_t *)(RCC_BASE + 0x00u))
|
||||
#define RCC_CR_HSI48ON (1u << 12)
|
||||
#define RCC_CR_HSI48RDY (1u << 13)
|
||||
#define RCC_CCIPR5 (*(volatile uint32_t *)(RCC_BASE + 0xE8u))
|
||||
#define RCC_CCIPR5_RNGSEL_Msk (3u << 4)
|
||||
|
||||
/* RNG peripheral */
|
||||
#ifdef STM32H5_TZEN
|
||||
#define RNG_BASE 0x520C0800u
|
||||
#else
|
||||
#define RNG_BASE 0x420C0800u
|
||||
#endif
|
||||
|
||||
#define RNG_CR (*(volatile uint32_t *)(RNG_BASE + 0x00u))
|
||||
#define RNG_SR (*(volatile uint32_t *)(RNG_BASE + 0x04u))
|
||||
#define RNG_DR (*(volatile uint32_t *)(RNG_BASE + 0x08u))
|
||||
#define RNG_CR_RNGEN (1u << 2)
|
||||
#define RNG_CR_CONDRST (1u << 30)
|
||||
#define RNG_CR_CONFIG3_SHIFT 8u
|
||||
#define RNG_CR_CONFIG2_SHIFT 13u
|
||||
#define RNG_CR_CLKDIV_SHIFT 16u
|
||||
#define RNG_CR_CONFIG1_SHIFT 20u
|
||||
#define RNG_SR_DRDY (1u << 0)
|
||||
#define RNG_SR_CECS (1u << 1)
|
||||
#define RNG_SR_SECS (1u << 2)
|
||||
#define RNG_SR_CEIS (1u << 5)
|
||||
#define RNG_SR_SEIS (1u << 6)
|
||||
|
||||
static void rng_init(void)
|
||||
{
|
||||
uint32_t rng_cr;
|
||||
|
||||
/* Enable HSI48 as RNG kernel clock source */
|
||||
RCC_CR |= RCC_CR_HSI48ON;
|
||||
while ((RCC_CR & RCC_CR_HSI48RDY) == 0u) { }
|
||||
|
||||
/* Select HSI48 for RNG clock */
|
||||
RCC_CCIPR5 &= ~RCC_CCIPR5_RNGSEL_Msk;
|
||||
RCC_AHB2ENR |= (1u << 18); /* RNG clock enable */
|
||||
delay(100);
|
||||
|
||||
/* Configure and enable RNG with conditioning reset */
|
||||
rng_cr = RNG_CR;
|
||||
rng_cr &= ~(0x1Fu << RNG_CR_CONFIG1_SHIFT);
|
||||
rng_cr &= ~(0x7u << RNG_CR_CLKDIV_SHIFT);
|
||||
rng_cr &= ~(0x3u << RNG_CR_CONFIG2_SHIFT);
|
||||
rng_cr &= ~(0x7u << RNG_CR_CONFIG3_SHIFT);
|
||||
rng_cr |= 0x0Fu << RNG_CR_CONFIG1_SHIFT;
|
||||
rng_cr |= 0x0Du << RNG_CR_CONFIG3_SHIFT;
|
||||
|
||||
RNG_CR = RNG_CR_CONDRST | rng_cr;
|
||||
while ((RNG_CR & RNG_CR_CONDRST) == 0u) { }
|
||||
RNG_CR = rng_cr | RNG_CR_RNGEN;
|
||||
while ((RNG_SR & RNG_SR_DRDY) == 0u) { }
|
||||
}
|
||||
|
||||
static int rng_get_word(uint32_t *out)
|
||||
{
|
||||
uint32_t timeout = 100000u;
|
||||
while ((RNG_SR & RNG_SR_DRDY) == 0u) {
|
||||
if ((RNG_SR & (RNG_SR_CECS | RNG_SR_SECS | RNG_SR_CEIS | RNG_SR_SEIS))
|
||||
!= 0u) {
|
||||
rng_init();
|
||||
timeout = 100000u;
|
||||
continue;
|
||||
}
|
||||
if (--timeout == 0u)
|
||||
return -1;
|
||||
}
|
||||
*out = RNG_DR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* wolfCrypt custom RNG block generator using STM32H5 TRNG */
|
||||
int custom_rand_gen_block(unsigned char *output, unsigned int sz)
|
||||
{
|
||||
uint32_t word;
|
||||
while (sz >= 4u) {
|
||||
if (rng_get_word(&word) != 0)
|
||||
return -1;
|
||||
output[0] = (unsigned char)word;
|
||||
output[1] = (unsigned char)(word >> 8);
|
||||
output[2] = (unsigned char)(word >> 16);
|
||||
output[3] = (unsigned char)(word >> 24);
|
||||
output += 4;
|
||||
sz -= 4;
|
||||
}
|
||||
if (sz > 0u) {
|
||||
if (rng_get_word(&word) != 0)
|
||||
return -1;
|
||||
while (sz-- > 0u) {
|
||||
*output++ = (unsigned char)word;
|
||||
word >>= 8;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* hal_init - platform initialization entry point */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void hal_init(void)
|
||||
{
|
||||
uart_init();
|
||||
rng_init();
|
||||
}
|
||||
|
||||
/* Custom time function */
|
||||
unsigned long my_time(unsigned long* timer)
|
||||
{
|
||||
static unsigned long t = 1000;
|
||||
if (timer)
|
||||
*timer = t;
|
||||
return t++;
|
||||
}
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
/* user_settings.h
|
||||
*
|
||||
* Minimal wolfCrypt configuration for bare-metal SRAM PUF example.
|
||||
* Target: Cortex-M (tested on NUCLEO-H563ZI)
|
||||
*
|
||||
* Copyright (C) 2006-2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfSSL.
|
||||
*
|
||||
* wolfSSL is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfSSL is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
|
||||
#ifndef WOLFSSL_USER_SETTINGS_H
|
||||
#define WOLFSSL_USER_SETTINGS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Platform */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
#define WOLFCRYPT_ONLY
|
||||
#define SINGLE_THREADED
|
||||
#define WOLFSSL_SMALL_STACK
|
||||
#define WOLFSSL_GENERAL_ALIGNMENT 4
|
||||
#define WOLFSSL_USER_IO
|
||||
#ifndef USE_WOLF_ARM_STARTUP
|
||||
#define USE_WOLF_ARM_STARTUP
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* PUF (Physically Unclonable Function) */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
#define WOLFSSL_PUF
|
||||
#define WOLFSSL_PUF_SRAM
|
||||
|
||||
/* Enable test mode: allows synthetic SRAM data for testing without hardware.
|
||||
* Comment out to use real SRAM PUF on actual hardware. */
|
||||
#define WOLFSSL_PUF_TEST
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Required Dependencies */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* HKDF is required for PUF key derivation (wc_PufDeriveKey) */
|
||||
#define HAVE_HKDF
|
||||
|
||||
/* SHA-256 is required for PUF identity and HKDF */
|
||||
/* (enabled by default, do not define NO_SHA256) */
|
||||
|
||||
/* Uncomment to use SHA3-256 instead of SHA-256 for PUF identity and HKDF */
|
||||
/* #define WC_PUF_SHA3 */
|
||||
/* #define WOLFSSL_SHA3 */
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Math Configuration */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
#define WOLFSSL_SP_MATH_ALL
|
||||
#define WOLFSSL_SP_SMALL
|
||||
#define SP_WORD_SIZE 32
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Disable Unused Features */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
#define NO_RSA
|
||||
#define NO_DH
|
||||
#define NO_DSA
|
||||
#define NO_DES3
|
||||
#define NO_RC4
|
||||
#define NO_MD4
|
||||
#define NO_MD5
|
||||
#define NO_SHA
|
||||
#define NO_PSK
|
||||
#define NO_OLD_TLS
|
||||
#define NO_PWDBASED
|
||||
#define NO_CERTS
|
||||
#define NO_ASN
|
||||
#define NO_CODING
|
||||
#define NO_SIG_WRAPPER
|
||||
#define NO_AES
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* System */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
#define NO_FILESYSTEM
|
||||
#define NO_WRITEV
|
||||
#define NO_MAIN_DRIVER
|
||||
#define NO_DEV_RANDOM
|
||||
|
||||
#define BENCH_EMBEDDED
|
||||
#define WOLFSSL_IGNORE_FILE_WARN
|
||||
|
||||
/* Provide custom time function */
|
||||
#define USER_TICKS
|
||||
|
||||
/* Use STM32H5 hardware TRNG (implemented in stm32.c) */
|
||||
extern int custom_rand_gen_block(unsigned char *output, unsigned int sz);
|
||||
#define CUSTOM_RAND_GENERATE_BLOCK custom_rand_gen_block
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WOLFSSL_USER_SETTINGS_H */
|
||||
Loading…
Reference in New Issue