Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 18 additions & 8 deletions config/examples/polarfire_mpfs250.config
Original file line number Diff line number Diff line change
@@ -1,8 +1,22 @@
ARCH?=RISCV64
TARGET?=mpfs250

# ECC P384 + SHA384
SIGN?=ECC384
HASH?=SHA384
IMAGE_HEADER_SIZE=512
# Flash sector size (4KB typical)
WOLFBOOT_SECTOR_SIZE?=0x1000

# ML-DSA 87
#SIGN=ML_DSA
#HASH=SHA256
#ML_DSA_LEVEL=5
#IMAGE_SIGNATURE_SIZE=4627
#IMAGE_HEADER_SIZE=12288
# Flash sector size (16KB)
#WOLFBOOT_SECTOR_SIZE?=0x4000

WOLFBOOT_VERSION?=1
ARMORED?=0
DEBUG?=0
Expand All @@ -27,7 +41,6 @@ ELF?=1

# Use RISC-V assembly version of ECDSA and SHA
NO_ASM?=0
NO_ARM_ASM?=0
# Optional: Use smaller SHA512
#CFLAGS_EXTRA+=-DUSE_SLOW_SHA512

Expand All @@ -38,9 +51,6 @@ DISK_EMMC?=0
# DDR Address for wolfBoot to start from
WOLFBOOT_ORIGIN?=0x80000000

# Flash sector size (4KB typical)
WOLFBOOT_SECTOR_SIZE?=0x1000

# Load Partition to RAM Address
WOLFBOOT_LOAD_ADDRESS?=0x8E000000

Expand All @@ -56,10 +66,10 @@ CFLAGS_EXTRA+=-DDISK_BLOCK_SIZE=0x80000
WOLFBOOT_LOAD_DTS_ADDRESS?=0x8A000000

# Optional Encryption
#CUSTOM_ENCRYPT_KEY=1
#ENCRYPT=1
#ENCRYPT_WITH_AES256=1
#OBJS_EXTRA=src/my_custom_encrypt_key.o
CUSTOM_ENCRYPT_KEY=1
ENCRYPT=1
ENCRYPT_WITH_AES256=1
OBJS_EXTRA=src/my_custom_encrypt_key.o

# Optional EMMC_SD debugging logs
#CFLAGS_EXTRA+=-DDEBUG_MMC
Expand Down
187 changes: 149 additions & 38 deletions docs/Targets.md
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,7 @@ The PolarFire SoC is a 64-bit RISC-V SoC featuring a five-core CPU cluster (1×

`hal/mpfs250.c` - Hardware abstraction layer implementation (UART and uSD)
`hal/mpfs250.h` - Register definitions and hardware interfaces
`hal/mpfs250.ld` - Linker script for the platform
`hal/mpfs250.ld` - Linker script fopolarr the platform
`hal/mpfs.dts` - Device tree source
`hal/mpfs.yaml` - HSS payload generator configuration
`hal/mpfs250.its` - Example FIT image creation template
Expand Down Expand Up @@ -982,7 +982,7 @@ sudo dd if=wolfboot.bin of=/dev/sdc1 bs=512 && sudo cmp wolfboot.bin /dev/sdc1
# Extract GZIP compressed linux kernel to wolfboot root
gzip -cdvk ../yocto-dev-polarfire/build/tmp-glibc/work/mpfs_video_kit-oe-linux/linux-mchp/6.12.22+git/build/linux.bin > kernel.bin

# Create custom FIT image
# Create custom FIT ima.itsge
mkimage -f hal/mpfs250.its fitImage
FIT description: PolarFire SoC MPFS250T
Created: Tue Dec 23 11:29:02 2025
Expand Down Expand Up @@ -1062,10 +1062,89 @@ printf "0123456789abcdef0123456789abcdef0123456789abcdef" > /tmp/enc_key.der

The result is `fitImage_v1_signed_and_encrypted.bin`, which gets placed into your OFP_A or OFP_B partitions.

```sh
sudo dd if=fitImage_v1_signed_and_encrypted.bin of=/dev/sdd2 bs=512 status=progress && sudo cmp fitImage_v1_signed_and_encrypted.bin /dev/sdd2
sudo dd if=fitImage_v1_signed_and_encrypted.bin of=/dev/sdd3 bs=512 status=progress && sudo cmp fitImage_v1_signed_and_encrypted.bin /dev/sdd3
```

During boot, wolfBoot decrypts the image headers from disk to select the best candidate, loads and decrypts the full image to RAM, then verifies integrity and authenticity before booting. On successful boot, `wolfBoot_success()` clears the key from RAM.

See the [Encrypted Partitions](encrypted_partitions.md) documentation for additional details.

### PolarFire SoC with PQC (ML-DSA)

#### Configuration

Update your `.config` file with the following ML-DSA settings:

```makefile
# ML-DSA 87 (Category 5)
SIGN=ML_DSA
HASH=SHA256
ML_DSA_LEVEL=5
IMAGE_SIGNATURE_SIZE=4627
IMAGE_HEADER_SIZE=12288
WOLFBOOT_SECTOR_SIZE?=0x4000
```

**Important:** The `sign` tool requires `IMAGE_HEADER_SIZE` to be set as an environment variable, even if it's already configured in `.config`. This is because the sign tool reads the environment variable separately to determine the header size for padding. Without this, the sign tool may use a smaller default header size, causing a mismatch with wolfBoot's expected header size.

#### Signing and Encryption

```sh
# Sign and Encrypt with PQ ML-DSA 5 (87)
# NOTE: IMAGE_HEADER_SIZE must match the value in .config
IMAGE_HEADER_SIZE=12288 ML_DSA_LEVEL=5 ./tools/keytools/sign --ml_dsa --sha256 --aes256 --encrypt /tmp/enc_key.der \
fitImage wolfboot_signing_private_key.der 1
```

**ML-DSA Parameter Reference:**

| ML_DSA_LEVEL | Security Category | Signature Size | Private Key | Public Key | Recommended IMAGE_HEADER_SIZE |
|--------------|-------------------|----------------|-------------|------------|------------------------------|
| 2 | Category 2 | 2420 | 2560 | 1312 | 8192 |
| 3 | Category 3 | 3309 | 4032 | 1952 | 8192 |
| 5 | Category 5 | 4627 | 4896 | 2592 | 12288 |

For other ML-DSA levels, adjust `ML_DSA_LEVEL`, `IMAGE_SIGNATURE_SIZE`, and `IMAGE_HEADER_SIZE` accordingly in both `.config` and the signing command.

### PolarFire Performance Comparison

#### Binary Size Comparison

The following table compares wolfBoot binary sizes for different signature algorithms on PolarFire SoC (MPFS250):

| Algorithm | Hash | Text | Data | BSS | Total | Binary Size |
|-----------|------|------|------|-----|-------|-------------|
| ECC384 | SHA384 | 67.1 KB | 8 B | 3.0 KB | 70.2 KB | 68 KB |
| ML-DSA 87 | SHA256 | 63.9 KB | 0 B | 14.5 KB | 78.4 KB | 64 KB |

**Observations:**
- **Binary Size:** ML-DSA 87 produces a smaller binary (64 KB vs 68 KB) due to optimized post-quantum code paths
- **Memory Usage:** ML-DSA 87 uses more BSS (14.5 KB vs 3.0 KB) for signature verification buffers
- **Total Size:** ML-DSA 87 has a larger total memory footprint (78.4 KB vs 70.2 KB) primarily due to BSS requirements
- **Header Size:** ML-DSA 87 requires `IMAGE_HEADER_SIZE=12288` compared to ECC384's `IMAGE_HEADER_SIZE=512`

#### Boot Time Comparison

Boot time measurements on PolarFire SoC (RISC-V 64-bit U54 @ 625 MHz) for a 19MB encrypted FIT image:

| Algorithm | Hash | Load Time | Decrypt Time | Integrity Check | Signature Verify | Total Boot Time |
|-----------|------|-----------|--------------|-----------------|------------------|-----------------|
| ECC384 | SHA384 | ~800 ms | ~2900 ms | ~1500 ms | ~70 ms | ~5.3 seconds |
| ML-DSA 87 | SHA256 | ~835 ms | ~2900 ms | ~2100 ms | ~22 ms | ~5.9 seconds |

**Observations:**
- **Loading and Decryption:** Similar performance (~835 ms load, ~2900 ms decrypt) as these operations are independent of the signature algorithm.
- **Integrity Check:** ML-DSA 87 takes longer (~2100 ms vs ~1500 ms) due to SHA256 processing a larger header (12288 bytes vs 512 bytes).
- **Signature Verification:** ML-DSA 87 is significantly faster (~22 ms vs ~70 ms) due to efficient post-quantum signature verification.
- **Overall:** ML-DSA 87 adds approximately 600 ms to total boot time, primarily due to the larger header size requiring more hashing.

**Configuration Notes:**
- ML-DSA 87 requires `IMAGE_HEADER_SIZE=12288` and `WOLFBOOT_SECTOR_SIZE=0x4000`
- ECC384 uses `IMAGE_HEADER_SIZE=512` and `WOLFBOOT_SECTOR_SIZE=0x1000`
- Both configurations support AES-256 encryption with similar decryption performance

### PolarFire Soc Debugging

Start GDB server:
Expand Down Expand Up @@ -1153,48 +1232,80 @@ FDT: MAC1 = 00:04:A3:5B:22:89
RISC-V 64-bit U54 (RV64GC1) 625 MHz

```
./configure --enable-riscv-asm --enable-dilithium --enable-mlkem --enable-sp=yes
make
./wolfcrypt/benchmark/benchmark
------------------------------------------------------------------------------
wolfSSL version 5.8.4
------------------------------------------------------------------------------
Math: Multi-Precision: Wolf(SP) word-size=64 bits=3072 sp_int.c
Single Precision: ecc 256 rsa/dh 2048 3072 sp_c64.c
Assembly Speedups: RISCVASM ALIGN
wolfCrypt Benchmark (block bytes 1048576, min 1.0 sec each)
RNG 5 MiB took 1.232 seconds, 4.058 MiB/s
AES-128-CBC-enc 10 MiB took 1.182 seconds, 8.457 MiB/s
AES-128-CBC-dec 10 MiB took 1.166 seconds, 8.573 MiB/s
AES-192-CBC-enc 10 MiB took 1.378 seconds, 7.257 MiB/s
AES-192-CBC-dec 10 MiB took 1.362 seconds, 7.344 MiB/s
AES-256-CBC-enc 10 MiB took 1.569 seconds, 6.373 MiB/s
AES-256-CBC-dec 10 MiB took 1.556 seconds, 6.426 MiB/s
AES-128-GCM-enc 10 MiB took 1.956 seconds, 5.113 MiB/s
AES-128-GCM-dec 10 MiB took 1.955 seconds, 5.115 MiB/s
AES-192-GCM-enc 5 MiB took 1.075 seconds, 4.650 MiB/s
AES-192-GCM-dec 5 MiB took 1.074 seconds, 4.654 MiB/s
AES-256-GCM-enc 5 MiB took 1.172 seconds, 4.268 MiB/s
AES-256-GCM-dec 5 MiB took 1.170 seconds, 4.275 MiB/s
GMAC Table 4-bit 15 MiB took 1.133 seconds, 13.245 MiB/s
CHACHA 20 MiB took 1.107 seconds, 18.064 MiB/s
CHA-POLY 15 MiB took 1.060 seconds, 14.152 MiB/s
POLY1305 75 MiB took 1.044 seconds, 71.812 MiB/s
SHA 20 MiB took 1.139 seconds, 17.561 MiB/s
SHA-256 10 MiB took 1.069 seconds, 9.350 MiB/s
SHA-384 15 MiB took 1.072 seconds, 13.994 MiB/s
SHA-512 15 MiB took 1.072 seconds, 13.990 MiB/s
SHA-512/224 15 MiB took 1.068 seconds, 14.041 MiB/s
SHA-512/256 15 MiB took 1.066 seconds, 14.070 MiB/s
HMAC-SHA 20 MiB took 1.140 seconds, 17.542 MiB/s
HMAC-SHA256 10 MiB took 1.068 seconds, 9.366 MiB/s
HMAC-SHA384 15 MiB took 1.066 seconds, 14.076 MiB/s
HMAC-SHA512 15 MiB took 1.066 seconds, 14.077 MiB/s
PBKDF2 1 KiB took 1.024 seconds, 1.129 KiB/s
RSA 2048 public 800 ops took 1.142 sec, avg 1.427 ms, 700.575 ops/sec
RSA 2048 private 100 ops took 8.450 sec, avg 84.504 ms, 11.834 ops/sec
DH 2048 key gen 60 ops took 1.010 sec, avg 16.841 ms, 59.379 ops/sec
DH 2048 agree 100 ops took 3.421 sec, avg 34.211 ms, 29.231 ops/sec
ECC [ SECP256R1] 256 key gen 100 ops took 1.304 sec, avg 13.039 ms, 76.691 ops/sec
ECDHE [ SECP256R1] 256 agree 100 ops took 1.299 sec, avg 12.992 ms, 76.970 ops/sec
ECDSA [ SECP256R1] 256 sign 100 ops took 1.338 sec, avg 13.383 ms, 74.723 ops/sec
ECDSA [ SECP256R1] 256 verify 200 ops took 1.846 sec, avg 9.231 ms, 108.333 ops/sec
RNG 5 MiB took 1.225 seconds, 4.081 MiB/s
AES-128-CBC-enc 10 MiB took 1.179 seconds, 8.478 MiB/s
AES-128-CBC-dec 10 MiB took 1.164 seconds, 8.589 MiB/s
AES-192-CBC-enc 10 MiB took 1.373 seconds, 7.281 MiB/s
AES-192-CBC-dec 10 MiB took 1.360 seconds, 7.354 MiB/s
AES-256-CBC-enc 10 MiB took 1.565 seconds, 6.389 MiB/s
AES-256-CBC-dec 10 MiB took 1.550 seconds, 6.451 MiB/s
AES-128-GCM-enc 10 MiB took 1.940 seconds, 5.156 MiB/s
AES-128-GCM-dec 10 MiB took 1.938 seconds, 5.159 MiB/s
AES-192-GCM-enc 5 MiB took 1.068 seconds, 4.680 MiB/s
AES-192-GCM-dec 5 MiB took 1.066 seconds, 4.689 MiB/s
AES-256-GCM-enc 5 MiB took 1.163 seconds, 4.298 MiB/s
AES-256-GCM-dec 5 MiB took 1.163 seconds, 4.301 MiB/s
GMAC Table 4-bit 15 MiB took 1.106 seconds, 13.566 MiB/s
CHACHA 20 MiB took 1.107 seconds, 18.068 MiB/s
CHA-POLY 15 MiB took 1.058 seconds, 14.178 MiB/s
POLY1305 75 MiB took 1.036 seconds, 72.387 MiB/s
SHA 20 MiB took 1.141 seconds, 17.535 MiB/s
SHA-256 10 MiB took 1.071 seconds, 9.336 MiB/s
SHA-384 15 MiB took 1.066 seconds, 14.068 MiB/s
SHA-512 15 MiB took 1.066 seconds, 14.070 MiB/s
SHA-512/224 15 MiB took 1.067 seconds, 14.060 MiB/s
SHA-512/256 15 MiB took 1.070 seconds, 14.023 MiB/s
SHA3-224 15 MiB took 1.328 seconds, 11.292 MiB/s
SHA3-256 15 MiB took 1.398 seconds, 10.731 MiB/s
SHA3-384 10 MiB took 1.206 seconds, 8.291 MiB/s
SHA3-512 10 MiB took 1.729 seconds, 5.785 MiB/s
SHAKE128 15 MiB took 1.142 seconds, 13.135 MiB/s
SHAKE256 15 MiB took 1.402 seconds, 10.699 MiB/s
HMAC-SHA 20 MiB took 1.145 seconds, 17.470 MiB/s
HMAC-SHA256 10 MiB took 1.074 seconds, 9.310 MiB/s
HMAC-SHA384 15 MiB took 1.076 seconds, 13.944 MiB/s
HMAC-SHA512 15 MiB took 1.069 seconds, 14.036 MiB/s
PBKDF2 1 KiB took 1.023 seconds, 1.130 KiB/s
RSA 2048 public 1000 ops took 1.087 sec, avg 1.087 ms, 920.244 ops/sec
RSA 2048 private 100 ops took 5.410 sec, avg 54.100 ms, 18.484 ops/sec
DH 2048 key gen 48 ops took 1.004 sec, avg 20.920 ms, 47.801 ops/sec
DH 2048 agree 100 ops took 2.087 sec, avg 20.873 ms, 47.909 ops/sec
ECC [ SECP256R1] 256 key gen 800 ops took 1.100 sec, avg 1.375 ms, 727.248 ops/sec
ECDHE [ SECP256R1] 256 agree 300 ops took 1.041 sec, avg 3.470 ms, 288.152 ops/sec
ECDSA [ SECP256R1] 256 sign 600 ops took 1.144 sec, avg 1.907 ms, 524.370 ops/sec
ECDSA [ SECP256R1] 256 verify 300 ops took 1.173 sec, avg 3.909 ms, 255.844 ops/sec
ECC [ SECP384R1] 384 key gen 100 ops took 3.887 sec, avg 38.867 ms, 25.729 ops/sec
ECDHE [ SECP384R1] 384 agree 100 ops took 3.883 sec, avg 38.827 ms, 25.755 ops/sec
ECDSA [ SECP384R1] 384 sign 100 ops took 3.948 sec, avg 39.485 ms, 25.326 ops/sec
ECDSA [ SECP384R1] 384 verify 100 ops took 2.619 sec, avg 26.190 ms, 38.183 ops/sec
ML-KEM 512 128 key gen 2000 ops took 1.021 sec, avg 0.511 ms, 1958.111 ops/sec
ML-KEM 512 128 encap 1700 ops took 1.006 sec, avg 0.592 ms, 1690.275 ops/sec
ML-KEM 512 128 decap 1300 ops took 1.075 sec, avg 0.827 ms, 1209.214 ops/sec
ML-KEM 768 192 key gen 1200 ops took 1.035 sec, avg 0.863 ms, 1158.970 ops/sec
ML-KEM 768 192 encap 1100 ops took 1.092 sec, avg 0.993 ms, 1006.925 ops/sec
ML-KEM 768 192 decap 800 ops took 1.055 sec, avg 1.319 ms, 758.026 ops/sec
ML-KEM 1024 256 key gen 800 ops took 1.124 sec, avg 1.405 ms, 711.862 ops/sec
ML-KEM 1024 256 encap 700 ops took 1.090 sec, avg 1.557 ms, 642.343 ops/sec
ML-KEM 1024 256 decap 600 ops took 1.181 sec, avg 1.968 ms, 508.073 ops/sec
ML-DSA 44 key gen 600 ops took 1.107 sec, avg 1.844 ms, 542.217 ops/sec
ML-DSA 44 sign 200 ops took 1.144 sec, avg 5.719 ms, 174.842 ops/sec
ML-DSA 44 verify 600 ops took 1.146 sec, avg 1.910 ms, 523.569 ops/sec
ML-DSA 65 key gen 400 ops took 1.267 sec, avg 3.167 ms, 315.744 ops/sec
ML-DSA 65 sign 200 ops took 1.687 sec, avg 8.436 ms, 118.543 ops/sec
ML-DSA 65 verify 400 ops took 1.272 sec, avg 3.180 ms, 314.428 ops/sec
ML-DSA 87 key gen 200 ops took 1.066 sec, avg 5.331 ms, 187.588 ops/sec
ML-DSA 87 sign 100 ops took 1.162 sec, avg 11.617 ms, 86.084 ops/sec
ML-DSA 87 verify 200 ops took 1.077 sec, avg 5.385 ms, 185.704 ops/sec
Benchmark complete
```

Expand Down
13 changes: 13 additions & 0 deletions hal/mpfs250.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,19 @@ void hal_init(void)
{
wolfBoot_printf("wolfBoot Version: %s (%s %s)\n",
LIBWOLFBOOT_VERSION_STRING,__DATE__, __TIME__);

#if defined(DISK_SDCARD) || defined(DISK_EMMC)
/* Initialize SDHCI for SDCard or eMMC */
if (sdhci_init() != 0) {
wolfBoot_printf("SDHCI initialization failed\n");
} else {
#ifdef DISK_EMMC
wolfBoot_printf("eMMC initialized successfully\n");
#else
wolfBoot_printf("SDCard initialized successfully\n");
#endif
}
#endif
}

/* ============================================================================
Expand Down
1 change: 1 addition & 0 deletions include/user_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ extern int tolower(int c);
# define WOLFSSL_SHA3
# define WOLFSSL_SHAKE256
# define WOLFSSL_SHAKE128
# define WOLFSSL_SP_NO_DYN_STACK
#endif /* WOLFBOOT_SIGN_ML_DSA || WOLFBOOT_SIGN_SECONDARY_ML_DSA */

#ifdef WOLFBOOT_HASH_SHA3_384
Expand Down
3 changes: 2 additions & 1 deletion options.mk
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,7 @@ ifeq ($(SIGN),ML_DSA)
KEYGEN_OPTIONS+=--ml_dsa
SIGN_OPTIONS+=--ml_dsa
WOLFCRYPT_OBJS+= $(ML_DSA_OBJS)
WOLFCRYPT_OBJS+=$(MATH_OBJS)
CFLAGS+=-D"WOLFBOOT_SIGN_ML_DSA" $(ML_DSA_EXTRA)
ifneq ($(HASH),SHA3)
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sha3.o
Expand All @@ -417,7 +418,7 @@ ifeq ($(SIGN),ML_DSA)
ifeq ($(WOLFBOOT_SMALL_STACK),1)
$(error WOLFBOOT_SMALL_STACK with ML-DSA not supported yet)
else
STACK_USAGE=19544
STACK_USAGE=25000
endif
endif

Expand Down
Loading
Loading