Skip to content
Merged
30 changes: 30 additions & 0 deletions embedded/ti-c2000-f28p55x/Header/entropy_probe.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* entropy_probe.h
*
* 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 ENTROPY_PROBE_H
#define ENTROPY_PROBE_H

/* Raw entropy-source characterization image (make ENTROPY_PROBE=1).
* Dumps unconditioned samples over SCI; never returns. */
void entropy_probe_run(void);

#endif /* ENTROPY_PROBE_H */
1,458 changes: 1,458 additions & 0 deletions embedded/ti-c2000-f28p55x/Header/mldsa87_precomp_a.h

Large diffs are not rendered by default.

4,093 changes: 4,093 additions & 0 deletions embedded/ti-c2000-f28p55x/Header/mldsa_octet_kat.h

Large diffs are not rendered by default.

76 changes: 69 additions & 7 deletions embedded/ti-c2000-f28p55x/Header/user_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,16 @@ extern "C" {
#undef WOLFSSL_NO_ML_DSA_65
#define WOLFSSL_NO_ML_DSA_65

#ifdef WOLF_MLDSA_ALL_LEVELS
/* The octet-boundary KAT image (make MLDSA=1) verifies at all three parameter
* sets. Level 44 matters disproportionately here: it is the only one whose w1
* commitment encoder packs 6-bit values (mldsa_encode_w1_88_c), so it is the
* only one that exercises that packer's octet masking at CHAR_BIT == 16.
* Levels 65 and 87 pack 4-bit values, which cannot overflow an octet. */
#undef WOLFSSL_NO_ML_DSA_44
#undef WOLFSSL_NO_ML_DSA_65
#endif

/* Raw key/sig import - no ASN.1 (both modes). */
#undef WOLFSSL_MLDSA_NO_ASN1
#define WOLFSSL_MLDSA_NO_ASN1
Expand Down Expand Up @@ -194,7 +204,17 @@ extern "C" {
* time instead of pinning the whole l-vector (saves ~6 KB on ML-DSA-87).
* Measured on F28P55x: sizeof(wc_MlDsaKey) 20,048 -> 13,904 bytes. */
#undef WOLFSSL_MLDSA_VERIFY_SMALLEST_MEM
#ifndef WOLF_MLDSA_FAST_VERIFY
/* Smallest RAM: streams the signature's z vector one polynomial at a time, so
* each z is re-decoded and re-NTT'd k times instead of once. FASTVERIFY=1
* trades that RAM back for speed. */
#define WOLFSSL_MLDSA_VERIFY_SMALLEST_MEM
#else
/* Keep the whole z vector (+~6 KB RAM) and accumulate A.z in a 64-bit poly so
* one Montgomery reduction is done per coefficient instead of per (k,l) pair. */
#undef WOLFSSL_MLDSA_SMALL_MEM_POLY64
#define WOLFSSL_MLDSA_SMALL_MEM_POLY64
#endif
/* Optional on this part: also define WOLFSSL_MLDSA_ASSIGN_KEY to keep the
* public key in flash (by reference) instead of copying it into the key
* struct - that removes a further ~5 KB of RAM (the 2,592-octet public key is
Expand Down Expand Up @@ -329,6 +349,36 @@ extern "C" {
#define NO_AES
#endif

#ifdef WOLF_HWAES
/* Offload AES-ECB/CBC/CTR to the on-chip AESA block through the crypto
* callback framework. Software AES stays compiled in: a context opts into
* hardware with wc_AesInit(&aes, NULL, WOLFSSL_C2000_DEVID), while one
* initialised with INVALID_DEVID stays pure software. That is what lets the
* KAT harness cross-check the two in a single image, so deliberately do NOT
* define WOLF_CRYPTO_CB_ONLY_AES. */
#undef WOLF_CRYPTO_CB
#define WOLF_CRYPTO_CB
#undef WOLFSSL_C2000_AES
#define WOLFSSL_C2000_AES

/* HAVE_AES_ECB is what compiles wc_AesEcbEncrypt/Decrypt and, with it, the ECB
* crypto-callback hook the hardware port needs; WOLFSSL_AES_DIRECT alone only
* creates the callback plumbing, not the entry points. Kept inside the HWAES
* block: it also switches the software CTR path to the bulk-ECB strategy and
* costs code size, so a software-only AES=1 build should not pay for it. */
#undef HAVE_AES_ECB
#define HAVE_AES_ECB

/* Single source of truth for the AESA device id. ti-c2000.h defaults this to
* 0x2000 behind #ifndef, so setting it here wins and lets WC_USE_DEVID be
* derived from it: wolfcrypt_test and benchmark then target the same device
* the KAT harness passes to wc_AesInit(), with no literal to keep in sync. */
#undef WOLFSSL_C2000_DEVID
#define WOLFSSL_C2000_DEVID 0x2000
#undef WC_USE_DEVID
#define WC_USE_DEVID WOLFSSL_C2000_DEVID
#endif

/* Curve25519 (X25519) + Ed25519. Enabled with EXTRA_CFLAGS=--define=WOLF_25519
* (X25519=1 build). No __uint128_t and no SP-25519 backend on C28x, so the
* default fe[10] 32-bit-limb field arithmetic is used; Ed25519 reuses the
Expand Down Expand Up @@ -540,15 +590,27 @@ extern long my_time(long* t);
/* ------------------------------------------------------------------------- */
/* RNG - real SHA-256 Hash-DRBG seeded by a DEV-ONLY test seed */
/* ------------------------------------------------------------------------- */
/* The F28P550SJ has no hardware TRNG, so there is no real entropy source.
* WOLFSSL_GENSEED_FORTEST makes random.c supply a built-in wc_GenerateSeed
* (an incrementing test value) that feeds the standard SHA-256 Hash-DRBG.
* This exercises the real DRBG code path (what a production build with a TRNG
* would use) and lets random_test pass - but the seed is NOT random, so this
* is DEV/TEST ONLY and MUST NOT be shipped. Replace wc_GenerateSeed with a
* real TRNG before any production use. */
#ifdef WOLF_ENTROPY
/* Real entropy: the on-chip oscillator-jitter source. The F28P550SJ has no
* TRNG, but it does have two independent RC oscillators and a crystal-derived
* PLL, and a Dual-Clock Comparator that can count one against another. The
* LSB of that count is the noise bit; it is oversampled well past its measured
* min-entropy, health-tested per SP800-90B 4.4, SHA-256 conditioned, and fed
* to the same SHA-256 Hash-DRBG. See IDE/C2000/README.md in the wolfSSL tree
* for the on-hardware characterization. */
#undef WOLFSSL_C2000_ENTROPY
#define WOLFSSL_C2000_ENTROPY
#else
/* The F28P550SJ has no hardware TRNG, so without ENTROPY=1 there is no real
* entropy source. WOLFSSL_GENSEED_FORTEST makes random.c supply a built-in
* wc_GenerateSeed (an incrementing test value) that feeds the standard SHA-256
* Hash-DRBG. This exercises the real DRBG code path (what a production build
* with a TRNG would use) and lets random_test pass - but the seed is NOT
* random, so this is DEV/TEST ONLY and MUST NOT be shipped. Build with
* ENTROPY=1 for the real source. */
#undef WOLFSSL_GENSEED_FORTEST
#define WOLFSSL_GENSEED_FORTEST
#endif

/* Run every self-test to completion and report each, so macro_test (a 16-bit
* safe-math self-test that currently fails on C28x) does not abort the suite
Expand Down
122 changes: 108 additions & 14 deletions embedded/ti-c2000-f28p55x/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,16 @@ endif

CL := $(CGT_ROOT)/bin/cl2000

# Header/ must precede $(WOLFROOT): wolfSSL's documented user_settings.h
# workflow puts one at the wolfSSL tree root, which would otherwise shadow this
# example's and silently build a different configuration.
INCS := \
-I$(CGT_ROOT)/include \
-I$(DRV) \
-I$(DEV)/common/include \
-I$(DEV)/headers/include \
-I$(WOLFROOT) \
-I$(CURDIR)/Header
-I$(CURDIR)/Header \
-I$(WOLFROOT)

# --float_support=fpu32 and --abi=eabi must match the prebuilt driverlib.lib.
# Define WOLF_C2000_SCI_STDOUT to route printf to SCIA (XDS110 COM); omit it to
Expand Down Expand Up @@ -108,13 +111,47 @@ ifeq ($(MLKEM),1)
$(WOLFROOT)/wolfcrypt/src/wc_mlkem_poly.c
endif

# MLDSA=1 builds the octet-boundary KAT image: ML-DSA-44/65/87 verify,
# wc_MlDsaKey_VerifyCtxHash() over SHA-256/SHA-512, and a verify from a PACKED
# key and signature via wc_UnpackOctets(). All three parameter sets are
# compiled in, so the test/benchmark harness is dropped to make room.
# FASTVERIFY=1 trades RAM for ML-DSA verify speed: keeps the full z vector
# (drops WOLFSSL_MLDSA_VERIFY_SMALLEST_MEM) and enables the 64-bit accumulator.
FASTVERIFY ?= 0
ifeq ($(FASTVERIFY),1)
CFLAGS += --define=WOLF_MLDSA_FAST_VERIFY
endif

# SECUREBOOT=1 verifies a PACKED firmware image straight from flash in pure
# (non pre-hash) ML-DSA mode, streaming it through SHAKE-256 so the image is
# never resident. Standalone image, like MLDSA=1.
SECUREBOOT ?= 0
ifeq ($(SECUREBOOT),1)
CFLAGS += --define=WOLF_SECUREBOOT --define=WOLF_MLDSA_ALL_LEVELS
endif

# PRECOMPA=1 stores matrix A (expanded at build time from the fixed
# verification key) in flash, so verify skips the SHAKE128 rejection sampling.
PRECOMPA ?= 0
ifeq ($(PRECOMPA),1)
CFLAGS += --define=WOLFSSL_MLDSA_VERIFY_PRECOMP_A
endif

MLDSA ?= 0
ifeq ($(MLDSA),1)
CFLAGS += --define=WOLF_MLDSA_ALL_LEVELS
endif

# aes.c + wc_encrypt.c are wanted by AES=1, AESEXTRA=1 and HWAES=1. Each sets
# NEED_AES_CORE and the pair is appended once below: the build is a single
# cl2000 invocation, so a source listed twice multiply-defines at link.
NEED_AES_CORE := 0

# AES=1 adds AES-CBC/CTR/CFB/GCM (software, table-driven; GCM_SMALL GHASH).
AES ?= 0
ifeq ($(AES),1)
CFLAGS += --define=WOLF_AES
WC_SRCS += \
$(WOLFROOT)/wolfcrypt/src/aes.c \
$(WOLFROOT)/wolfcrypt/src/wc_encrypt.c
NEED_AES_CORE := 1
endif

# X25519=1 adds Curve25519 (X25519) + Ed25519 (default fe[10] 32-bit backend).
Expand Down Expand Up @@ -164,14 +201,24 @@ ifeq ($(AESEXTRA),1)
CFLAGS += --define=WOLF_AES --define=WOLF_AESEXTRA
WC_SRCS += \
$(WOLFROOT)/wolfcrypt/src/cmac.c
# aes.c and wc_encrypt.c are also pulled in by AES=1; add them here only when
# AES=1 did not, so they are not listed twice in the single cl2000 invocation
# (which would multiply-define their symbols at link).
ifneq ($(AES),1)
WC_SRCS += \
$(WOLFROOT)/wolfcrypt/src/aes.c \
$(WOLFROOT)/wolfcrypt/src/wc_encrypt.c
endif
NEED_AES_CORE := 1
endif

# HWAES=1 offloads AES-ECB/CBC/CTR to the on-chip AESA accelerator (TI EIP-120t
# at 0x42000) via crypto callbacks. Software AES stays compiled in so one image
# can compare both paths. Implies AES=1; driverlib.lib is already linked.
HWAES ?= 0
ifeq ($(HWAES),1)
CFLAGS += --define=WOLF_AES --define=WOLF_HWAES
# WC_USE_DEVID points wolfcrypt_test and benchmark at the hardware device;
# without it they init every Aes context with INVALID_DEVID and silently
# measure/test software only. It is derived from WOLFSSL_C2000_DEVID in
# Header/user_settings.h rather than repeated as a literal here, so the two
# cannot drift apart.
WC_SRCS += \
$(WOLFROOT)/wolfcrypt/src/cryptocb.c \
$(WOLFROOT)/wolfcrypt/src/port/ti/ti-c2000-aes.c
NEED_AES_CORE := 1
endif

# RSA=1 adds RSA verify (SP math backend, shared with the ECC P-256 build).
Expand Down Expand Up @@ -219,6 +266,8 @@ ifeq ($(DH),1)
$(WOLFROOT)/wolfcrypt/src/sp_c32.c
endif

HARNESS_EXTRA :=

HARNESS_SRCS := \
$(WOLFROOT)/wolfcrypt/test/test.c \
$(WOLFROOT)/wolfcrypt/benchmark/benchmark.c
Expand All @@ -245,6 +294,18 @@ ifeq ($(SIGN),1)
--define=NO_CRYPT_BENCHMARK
LNKCMD := $(CURDIR)/28p55x_wolf_sign_lnk.cmd
HARNESS_SRCS :=
else ifeq ($(SECUREBOOT),1)
CFLAGS += --define=NO_CRYPT_TEST --define=NO_CRYPT_BENCHMARK
LNKCMD := $(CURDIR)/28p55x_wolf_flash_lnk.cmd
HARNESS_SRCS :=
else ifeq ($(MLDSA),1)
ifeq ($(BENCH),1)
$(error MLDSA=1 and BENCH=1 are separate images - build them one at a time)
endif
CFLAGS += --define=WOLF_MLDSA_OCTETS --define=NO_CRYPT_TEST \
--define=NO_CRYPT_BENCHMARK
LNKCMD := $(CURDIR)/28p55x_wolf_flash_lnk.cmd
HARNESS_SRCS :=
else
LNKCMD := $(CURDIR)/28p55x_wolf_flash_lnk.cmd
ifeq ($(BENCH),1)
Expand All @@ -261,7 +322,40 @@ ifeq ($(MEMPROF),1)
CFLAGS += --define=WOLF_MEM_PROFILE
endif

ALL_SRCS := $(WC_SRCS) $(HARNESS_SRCS) $(BSP_SRCS) $(ASM_SRCS)
# ENTROPY=1 replaces the dev-only WOLFSSL_GENSEED_FORTEST counter with the real
# oscillator-jitter entropy source (DCC/INTOSC vs PLL, SHA-256 conditioned,
# SP800-90B health tests) feeding the SP800-90A Hash-DRBG.
ENTROPY ?= 0
ifeq ($(ENTROPY),1)
CFLAGS += --define=WOLF_ENTROPY
WC_SRCS += $(WOLFROOT)/wolfcrypt/src/port/ti/ti-c2000-entropy.c
endif

# ENTROPY_PROBE=1 builds the raw entropy-source characterization image: it
# dumps unconditioned DCC oscillator-jitter and ADC samples over SCI so a host
# can estimate min-entropy. Measurement only - no crypto runs.
ENTROPY_PROBE ?= 0
ifeq ($(ENTROPY_PROBE),1)
ifneq ($(SIGN)$(MLDSA)$(BENCH),000)
$(error ENTROPY_PROBE=1 is a standalone measurement image - build it on its own)
endif
# Nothing after entropy_probe_run() executes, so linking wolfcrypt_test and
# benchmark would only bloat the image.
CFLAGS += --define=NO_CRYPT_TEST --define=NO_CRYPT_BENCHMARK
HARNESS_SRCS :=
CFLAGS += --define=WOLF_ENTROPY_PROBE --define=NO_CRYPT_TEST \
--define=NO_CRYPT_BENCHMARK
HARNESS_EXTRA += $(CURDIR)/Source/entropy_probe.c
endif

# Append the shared AES core once, after every toggle has had its say.
ifeq ($(NEED_AES_CORE),1)
WC_SRCS += \
$(WOLFROOT)/wolfcrypt/src/aes.c \
$(WOLFROOT)/wolfcrypt/src/wc_encrypt.c
endif

ALL_SRCS := $(WC_SRCS) $(HARNESS_SRCS) $(HARNESS_EXTRA) $(BSP_SRCS) $(ASM_SRCS)

.PHONY: all clean

Expand Down
Loading
Loading