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
49 changes: 47 additions & 2 deletions .github/examples-manifest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -373,8 +373,8 @@ examples:
profile: crypto
mode: check

- id: embedded
path: embedded
- id: embedded-tls
path: embedded/tls
profile: default
run:
# the client receives the server's HTML: proves the full round-trip, not "Done"
Expand Down Expand Up @@ -1323,6 +1323,36 @@ examples:
tier: cross
profile: all
mode: build-only
# signature.yml compiles wolfcrypt from a wolfSSL source tree (WOLFROOT) and
# runs every example via verify_signature.sh, so these are not host-tier jobs
- id: embedded-signature
path: embedded/signature
tier: cross
profile: all
- id: embedded-signature-ecc-sign-verify
path: embedded/signature/ecc_sign_verify
tier: cross
profile: all
- id: embedded-signature-ecc-vfy-only
path: embedded/signature/ecc_vfy_only
tier: cross
profile: all
- id: embedded-signature-ecc-vfy-only-nonblock
path: embedded/signature/ecc_vfy_only_nonblock
tier: cross
profile: all
- id: embedded-signature-rsa-sign-verify
path: embedded/signature/rsa_sign_verify
tier: cross
profile: all
- id: embedded-signature-rsa-vfy-only
path: embedded/signature/rsa_vfy_only
tier: cross
profile: all
- id: embedded-signature-rsa-vfy-only-nonblock
path: embedded/signature/rsa_vfy_only_nonblock
tier: cross
profile: all
- id: uefi-static
path: uefi-static
tier: cross
Expand Down Expand Up @@ -1389,6 +1419,21 @@ examples:
mode: skip
reason: "shared ML-KEM crypto-callback source (pq/mlkem-cryptocb.c) linked by pq/ml_kem_cryptocb and pq/tls_cryptocb; not an example"

- id: efr32xg25
path: embedded/efr32xg25
mode: skip
reason: "EFR32xG25 board build via slc-cli and GNU Arm; output only comes back from the hardware"

- id: nuvoton-m2354
path: embedded/nuvoton_m2354
mode: skip
reason: "NuMaker-M2354 board build; tests run on the hardware only"

- id: nuvoton-m2354-secure
path: embedded/nuvoton_m2354/secure
mode: skip
reason: "secure-side NSC source linked into the nuvoton_m2354 board build; not an example"

- id: puf-host-test
path: puf/host_test
mode: skip
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ jobs:
with:
caller_run_id: ${{ github.run_id }}

signature:
needs: [refs]
uses: ./.github/workflows/signature.yml
with:
caller_run_id: ${{ github.run_id }}

infineon-psoc-e8:
needs: [refs]
uses: ./.github/workflows/infineon-psoc-e8.yml
Expand Down
69 changes: 69 additions & 0 deletions .github/workflows/signature.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: Signature

on:
push:
branches: [master]
paths:
- 'embedded/signature/**'
- '.github/workflows/signature.yml'
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
paths:
- 'embedded/signature/**'
- '.github/workflows/signature.yml'
# No cron: nightly.yml calls this, so the nightly stays one run and one triage writer
workflow_call:
inputs:
caller_run_id:
description: 'run id of the calling workflow; keeps a called run in its own concurrency group'
type: string
default: ''
workflow_dispatch:

# github.workflow is the CALLER's name in a called workflow, so hardcode ours
concurrency:
group: ${{ inputs.caller_run_id && format('signature-call-{0}', inputs.caller_run_id) || format('signature-{0}', github.ref) }}
cancel-in-progress: ${{ !inputs.caller_run_id }}

permissions:
contents: read

jobs:
resolve:
uses: ./.github/workflows/_resolve-wolfssl.yml
with:
stable_count: 1

signature:
needs: resolve
name: Run / ${{ matrix.example }} wolfSSL ${{ matrix.wolfssl_ref }}
if: github.event_name != 'pull_request' || github.event.pull_request.draft == false
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
example: [embedded/signature]
wolfssl_ref: ${{ fromJson(needs.resolve.outputs.refs_json) }}
timeout-minutes: 30
steps:
- uses: actions/checkout@v5

# The signature Makefiles set WOLFROOT and compile the needed
# wolfcrypt sources directly, so they need a wolfSSL source tree
# rather than an installed library.
- name: Fetch wolfSSL
run: |
set -euo pipefail
bash "$GITHUB_WORKSPACE/.github/scripts/git-clone-retry.sh" -q --depth 1 --branch '${{ matrix.wolfssl_ref }}' https://github.com/wolfSSL/wolfssl /tmp/wolfssl

# Builds and runs every example for each math/arch option and exits
# non-zero on any FAIL; unsupported combinations are reported as N/A.
- name: Build and run
run: ./${{ matrix.example }}/verify_signature.sh /tmp/wolfssl /tmp/signature-logs

- name: Upload logs
if: failure()
uses: actions/upload-artifact@v4
with:
name: signature-logs-${{ matrix.wolfssl_ref }}
path: /tmp/signature-logs
23 changes: 23 additions & 0 deletions embedded/signature/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
CC = gcc
#CC = clang
SRCROOT = .
ECCSRCDIRS := $(shell ls -d $(SRCROOT)/ecc_*)
RSASRCDIRS := $(shell ls -d $(SRCROOT)/rsa_*)

# All examples share the wolfCrypt objects in WOLFROOT, so build serially.
.NOTPARALLEL:

all: ecc rsa
Comment thread
miyazakh marked this conversation as resolved.
Resolved

ecc:
@for d in $(ECCSRCDIRS); do echo $$d ; $(MAKE) -C $$d CC=$(CC) || exit 1; done

rsa:
@for d in $(RSASRCDIRS); do echo $$d ; $(MAKE) -C $$d CC=$(CC) || exit 1; done

clean: FORCE
@for d in $(ECCSRCDIRS); do echo $$d ; $(MAKE) -C $$d clean; done
@for d in $(RSASRCDIRS); do echo $$d ; $(MAKE) -C $$d clean; done

FORCE:
.PHONY: FORCE
105 changes: 105 additions & 0 deletions embedded/signature/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Signature Examples for Embedded Systems
​
This directory includes the following examples. Each subdirectory has a Makefile, source files, and a README to show how to build the example, along with expected example output.
​
|Scheme|Directory|Description|
|---|---|---|
|RSA|rsa_sign_verify|sign/verify signature inline |
||rsa_vfy_only |verify signature|
||rsa_vfy_only_nonblock|verify signature with non-blocking|
|ECDSA|ecc_sign_verify|sign msg and verify signature|
||ecc_vfy_only|verify Signature|
||ecc_vfy_only_nonblock|verify signature with non-blocking|

NOTE: ECC non-blocking (`ecc_vfy_only_nonblock`) is supported only with SP math (`math=sp` or the default). wolfSSL does not provide ECC non-blocking for TFM, so building it with `math=tfm` fails with `#error ECC non-blocking only supports SP`. `arch=x64` also needs wolfSSL newer than v5.9.4.


When building each example, you can specify arguments to control the build. Specify a target function to run either a simple example, benchmark, or memory tracking example. Specify an "arch" option to build optimized code for MCU architectures such as Intel x86, ARM64 or a generic code by default. And specify a "math" option to choose an underlying wolfCrypt math library to use, between Single Precision or TFM.


```
$ make <Function> math=<Mathlib> arch=<MCU>
```
​
## Functions

|Function name|Description|
|---|---|
|Default|Simple Execution|
|mem|Memory Track on heap and stack usage|
|bench|Performance benchmark|

## Math library
|math|Description|
|---|---|
|Default|Generic architecture by pure C language source code|
|sp| SP for generic or specified architecture|
|tfm|TFM for generic architecture|
## MCU Architectures
NOTE: No architecture specification is required when using TFM.
|arch|Description|
|---|---|
|Default|Generic architecture by pure C language source code|
|c32| SP using 32-bit data type |
|c64| SP using 64-bit data type (default) |
|arm64|SP for ARM64 |
|x64|SP for x86 64bit|

## Verify all examples

`verify_signature.sh` builds and runs every example for each math/arch option and prints OK/FAIL per target (unsupported combinations are shown as N/A). Logs are saved to `verify_logs/`.

```bash
./verify_signature.sh [path to wolfssl]
```

NOTE: Each build deletes `wolfcrypt/src/*.o` in the wolfSSL directory.


Each Makefile is self-contained to statically link wolfCrypt source files (without using a shared libwolfssl.so). Put your wolfSSL source files in parallel with the wolfssl-examples directory. The location of the primary wolfSSL source directory is defined by WOLFROOT in each Makefile. Each build compiles only the needed files for the target. OBJ and OBJ_xxx macros in each Makefile define object files for the common and specific target.
​
Example programs are hard coded to use a specific hash algorithm or signature scheme. Sha256 is used for the hash by default. PKCS#1 v1.5 or ECDSA is used for the signature scheme. You can refer to the following API tables for modifying the examples for other algorithms or schemes.

## Table 1: Hash algorithms for PKCS#1 Signature
|Algorithm|Src File|Macro SW<br>Enable|<br>Disable|Note|
|---|---|---|---|---|
|MD2|md2.c|WOLFSSL_MD2||Only for v1.5 Backward compatibility|
|MD5|md5.c||NO_MD5|Only for v1.5 Backward compatibility|
|SHA1|sha.c||NO_SHA|||SHA256|sha256.c||NO_SHA256|
||SHA384|sha512.c|WOLFSSL_SHA384||Disabled by default|
|SHA512|sha512.c|WOLFSSL_SHA512||Disabled by default|


## Table 2: Hash Algorithm APIs
|Algorithm|<br>Init|API<br>Update|<br>Final|
|---|---|---|---|
|MD2|wc_InitMd2|wc_Md2Update|wc_Md2Final|
|MD5|wc_InitMd5|wc_Md5Update|wc_Md5Final|
|SHA1|wc_InitSha|wc_ShaUpdate|wc_ShaFinal|
|SHA256|wc_InitSha256|wc_Sha256Update|wc_Sha256Final|
|SHA384|wc_initSha384|wc_Sha384Update|wc_Sha384Final|
|SHA512|wc_InitSha512|wc_Sha512Update|wc_Sha512Final|

​
## Table 3: RSA Signature APIs
​
|Padding|API|Description|
|---|---|---|
|PKCS #1 v1.5|wc_RsaSSL_Verify|Decrypt input signature to verify|
||wc_RsaSSL_VerifyInline|The output uses the same byte array as the input|
|PSS|wc_RsaPSS_Verify|Decrypt input signature to verify with PSS|
| |wc_RsaPSS_VerifyCheck|Verify the message signed|
| |wc_RsaPSS_VerifyCheck_ex|with Salt length argument|
| |wc_RsaPSS_VerifyInline|The output uses the same byte array as the input|
| |wc_RsaPSS_VerifyCheckInline|Verify the message signed|
| |wc_RsaPSS_VerifyCheckPadding|Checks the PSS data to ensure that the signature matches|
| |wc_RsaPSS_VerifyCheckPadding_ex|with Salt length argument|


## Table 4: ECC Signature APIs
​
|Algorithm|API|Hash|
|---|---|---|
|ECDSA|wc_ecc_sign_hash|SHA512|
|Ed25519|wc_ed25519_sign_hash|SHA512|
|Ed488|wc_ed488_sign_hash|SHAKE256|
85 changes: 85 additions & 0 deletions embedded/signature/ecc_sign_verify/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# The path to the wolfssl directory must be set correctly for your environment.
WOLFROOT = ../../../../wolfssl

CFLAGS = $(EX_CFLAGS) -DWOLFSSL_USER_SETTINGS -I. -I$(WOLFROOT) -Os
ASFLAGS = -DWOLFSSL_USER_SETTINGS -I. -I$(WOLFROOT)

OBJ=\
$(WOLFROOT)/wolfcrypt/src/ecc.o\
$(WOLFROOT)/wolfcrypt/src/sha256.o\
$(WOLFROOT)/wolfcrypt/src/hash.o\
$(WOLFROOT)/wolfcrypt/src/random.o\
$(WOLFROOT)/wolfcrypt/src/asn.o\
$(WOLFROOT)/wolfcrypt/src/wc_port.o\
$(WOLFROOT)/wolfcrypt/src/coding.o\
$(WOLFROOT)/wolfcrypt/src/memory.o\
$(WOLFROOT)/wolfcrypt/src/wolfmath.o\
$(WOLFROOT)/wolfcrypt/src/wc_encrypt.o\

OBJ_SP_C32 := \
$(WOLFROOT)/wolfcrypt/src/sp_int.o\
$(WOLFROOT)/wolfcrypt/src/sp_c32.o\

OBJ_SP_C64 := \
$(WOLFROOT)/wolfcrypt/src/sp_int.o\
$(WOLFROOT)/wolfcrypt/src/sp_c64.o\

OBJ_SP_ARM64 := \
$(WOLFROOT)/wolfcrypt/src/sp_int.o\
$(WOLFROOT)/wolfcrypt/src/sp_arm64.o\

OBJ_SP_X86_64 := \
$(WOLFROOT)/wolfcrypt/src/sp_int.o\
$(WOLFROOT)/wolfcrypt/src/cpuid.o\
$(WOLFROOT)/wolfcrypt/src/sp_x86_64.o\
$(WOLFROOT)/wolfcrypt/src/sp_x86_64_asm.o\

OBJ_TFM := \
$(WOLFROOT)/wolfcrypt/src/tfm.o\

.PHONY: all clean mem size bench
# Every target depends on "clean", which deletes the wolfCrypt objects.
# Running in parallel would race with that, so force serial execution.
.NOTPARALLEL:

# Memory tracking (DEBUG_MEMORY) also has to be enabled in memory.c, so
# compile it together with the example instead of linking memory.o.
OBJ_MEM = $(WOLFROOT)/wolfcrypt/src/memory.c \
$(filter-out $(WOLFROOT)/wolfcrypt/src/memory.o,$(OBJ))

ifeq ($(math) $(arch),sp x64)
ASFLAGS+= -DSP_X86_64_FLAG
CFLAGS += -DSP_X86_64_FLAG
OBJ += $(OBJ_SP_X86_64)
else ifeq ($(math) $(arch),sp arm64)
CFLAGS += -DSP_ARM64_FLAG
OBJ += $(OBJ_SP_ARM64)
else ifeq ($(math) $(arch),sp c64)
CFLAGS += -DSP_C64_FLAG
OBJ += $(OBJ_SP_C64)
else ifeq ($(math) $(arch),sp c32)
CFLAGS += -DSP_C32_FLAG
OBJ += $(OBJ_SP_C32)
else ifeq ($(math), tfm)
CFLAGS += -DTFM_FLAG
OBJ += $(OBJ_TFM)
else
CFLAGS += -DSP_C64_FLAG
OBJ += $(OBJ_SP_C64)
endif

all : ecc_sign_verify bench mem

ecc_sign_verify: clean $(OBJ)
$(CC) $(CFLAGS) -o ecc_sign_verify ecc_sign_verify.c $(OBJ)

bench: clean $(OBJ)
$(CC) $(CFLAGS) -DBENCHMARK -o ecc_sign_verify_bench ecc_sign_verify.c $(OBJ) -lpthread

mem: clean $(OBJ)
$(CC) $(CFLAGS) -DDEBUG_MEMORY -o ecc_sign_verify_mem ecc_sign_verify.c $(OBJ_MEM) -lpthread
clean:
rm -f ecc_sign_verify ecc_sign_verify_bench ecc_sign_verify_mem $(WOLFROOT)/wolfcrypt/src/*.o

size :
size $(OBJ) ecc_sign_verify
Loading
Loading