Skip to content
Draft
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
89 changes: 89 additions & 0 deletions .github/workflows/ti-c2000-compile.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
name: TI C2000 (C28x) compile-only

# Compile-guard for the TI C2000 C28x port (CHAR_BIT == 16). It builds the
# wolfCrypt subset that carries the CHAR_BIT != 8 gated fixes with the TI cl2000
# code generation tools - no linking, no C2000Ware, no hardware. Purpose: catch
# compile regressions in the octet/SP/ML-DSA gated paths. On-target run-tests
# live on a hardware-in-the-loop runner (there is no public C28x simulator).

# START OF COMMON SECTION
on:
# Only build when something that can affect the C28x compile changes, so the
# job (and the CGT it pulls) does not burn runner minutes on unrelated PRs.
push:
branches: [ 'master', 'main', 'release/**' ]
paths:
- 'wolfcrypt/src/**'
- 'wolfssl/wolfcrypt/**'
- 'IDE/C2000/**'
- '.github/workflows/ti-c2000-compile.yml'
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
branches: [ '*' ]
paths:
- 'wolfcrypt/src/**'
- 'wolfssl/wolfcrypt/**'
- 'IDE/C2000/**'
- '.github/workflows/ti-c2000-compile.yml'

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# END OF COMMON SECTION

jobs:
ti_c2000_compile:
name: cl2000 compile-only
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.draft == false }}
runs-on: ubuntu-22.04
timeout-minutes: 20
env:
# TI C2000 code generation tools. The CGT is a free download from TI.
# Update CGT_VER / CGT_URL when bumping the toolchain. If the TI URL
# starts requiring a click-through, host the installer as a repo/org
# cache artifact and point CGT_URL at it (the cache step below makes the
# download a once-per-version cost).
CGT_VER: "22.6.2.LTS"
CGT_URL: "https://dr-download.ti.com/software-development/ide-configuration-compiler-or-debugger/MD-LP0nQ4O8eX/22.6.2.LTS/ti_cgt_c2000_22.6.2.LTS_linux-x64_installer.bin"
# SHA-256 of the installer at CGT_URL. Set this to pin/verify the download
# (recommended); the printed hash from a prior run can be pasted here. Left
# empty the job runs unpinned and only warns.
CGT_SHA256: ""
CGT_DIR: "${{ github.workspace }}/ti-cgt-c2000"
steps:
- uses: actions/checkout@v4
name: Checkout wolfSSL

- name: Cache TI C2000 CGT
id: cgt-cache
uses: actions/cache@v4
with:
path: ${{ env.CGT_DIR }}
key: ti-cgt-c2000-${{ env.CGT_VER }}

- name: Download + install TI C2000 CGT
if: steps.cgt-cache.outputs.cache-hit != 'true'
run: |
set -e
curl -fsSL "$CGT_URL" -o /tmp/cgt.bin
if [ -n "$CGT_SHA256" ]; then
echo "$CGT_SHA256 /tmp/cgt.bin" | sha256sum -c -
else
echo "::warning::CGT_SHA256 is unset - the TI CGT installer is not" \
"integrity-checked. Pin it with the hash below." >&2
sha256sum /tmp/cgt.bin
fi
chmod +x /tmp/cgt.bin
/tmp/cgt.bin --mode unattended --prefix "$CGT_DIR"

- name: Locate cl2000
id: find-cl
run: |
CL=$(find "$CGT_DIR" -type f -name cl2000 | head -1)
test -n "$CL" || { echo "cl2000 not found under $CGT_DIR"; exit 1; }
echo "cgt_root=$(dirname "$(dirname "$CL")")" >> "$GITHUB_OUTPUT"

- name: Compile-only guard
run: |
CGT_ROOT="${{ steps.find-cl.outputs.cgt_root }}" \
IDE/C2000/compile.sh
7 changes: 7 additions & 0 deletions .wolfssl_known_macro_extras
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,7 @@ WOLFSSL_CLANG_TIDY
WOLFSSL_CLIENT_EXAMPLE
WOLFSSL_CONTIKI
WOLFSSL_CRL_ALLOW_MISSING_CDP
WOLFSSL_DILITHIUM_VERIFY_SMALLEST_MEM
WOLFSSL_DISABLE_EARLY_SANITY_CHECKS
WOLFSSL_DRBG_SHA256
WOLFSSL_DTLS13_ECHO_LEGACY_SESSION_ID
Expand Down Expand Up @@ -1115,6 +1116,12 @@ __SUNPRO_CC
__SVR4
__TASKING__
__TI_COMPILER_VERSION__
__TMS320C2000__
__TMS320C2800__
__TMS320C28XX__
__TMS320C54X__
__TMS320C5500__
__TMS320C55X__
__TURBOC__
__UNIX__
__USE_GNU
Expand Down
79 changes: 79 additions & 0 deletions IDE/C2000/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# TI C2000 C28x (CHAR_BIT == 16) support

wolfCrypt builds and runs on the TI C2000 C28x DSP family, a word-addressed
architecture where `CHAR_BIT == 16` (a C `char`/`unsigned char` is 16 bits and
is the smallest addressable unit). Support is gated behind `WOLFSSL_WIDE_BYTE`,
which `wolfssl/wolfcrypt/types.h` auto-enables when `CHAR_BIT != 8` or a known
16-bit-char TI toolchain macro is seen (`__TMS320C28XX__`, `__TMS320C2000__`,
etc.). On normal 8-bit-byte targets none of this code changes behavior.

## Validated on hardware (LAUNCHXL-F28P55X, TMS320F28P550SJ, cl2000)

- SHA-1; SHA-224/256, SHA-384/512, SHA-512/224, SHA-512/256
- SHA3-224/256/384/512, SHAKE128/256 (split-64 Keccak permutation auto-enabled
for `WOLFSSL_WIDE_BYTE`, ~53% faster than the generic C path)
- ML-DSA-44/65/87 (Dilithium) verify and full keygen/sign/verify;
ML-KEM-512/768/1024 (FIPS 203)
- AES-128/192/256 CBC/CTR/CFB/OFB/GCM/XTS; AES-CMAC, AES-CCM, AES-GMAC,
AES-SIV, AES-EAX
- HMAC + HKDF; ChaCha20-Poly1305; Poly1305
- X25519 + Ed25519; X448 + Ed448 (CURVE448_SMALL/ED448_SMALL byte backend)
- ECDSA + ECDH (SECP256R1, SP math)
- RSA-2048 PKCS#1 v1.5 sign and verify; DH FFDHE-2048 (SP math)

The on-target acceptance gate is the per-algorithm KAT set the reference example
prints over JTAG (e.g. `ML-DSA-87 verify KAT: PASS`, `X448 a*Bpub: PASS`); the
split-64 Keccak path is additionally validated on a host build with
`-DWC_SHA3_SPLIT64` forced, and the compile-only CI below guards every
`WOLFSSL_WIDE_BYTE` source against build breakage.

## What `WOLFSSL_WIDE_BYTE` fixes

The `CHAR_BIT != 8` work falls into a few recurring classes, each a no-op on
8-bit targets:

- Byte/word aliasing. Serializing a `word32`/`word64` via a `byte*` cast moves
cells, not octets. Replaced with shift-based octet I/O. Shared helpers live in
`wolfcrypt/src/misc.c`: `WordsFromBytesBE32`/`BytesFromWordsBE32`,
`BytesFromWordsLE32`, the 64-bit variants, and octet-correct
`readUnalignedWord32`/`readUnalignedWord64`. `sp_int.c sp_read_unsigned_bin`
uses the endian-/`CHAR_BIT`-agnostic shift loop for its leftover bytes.
- `(byte)x` not truncating to an octet (it keeps 16 bits). Masked with
`WC_OCTET(x)` = `(byte)((x) & 0xFF)` (types.h). Used across the ML-KEM/ML-DSA
encoders, the SP `*_to_bin` serializers, AES `GETBYTE`, base64, and DRBG.
- Integer-promotion bugs. `1U << n` is 16-bit on C28x (use `1UL`); a bit width
written `sizeof(t) * 8` is wrong when `CHAR_BIT != 8` (use `CHAR_BIT *
sizeof(t)`); a `byte` operand promotes to a 16-bit `int`.
- `sizeof` counting cells, not octets. e.g. `CHACHA_CHUNK_BYTES` is `16 * 4`,
not `16 * sizeof(word32)` (= 32 on C28x, which halves the ChaCha block).

The SP backend file `wolfcrypt/src/sp_c32.c` is generated; the `& 0xFF` octet
masks added to its `sp_*_to_bin_*` serializers are also applied in the SP
generator templates so a regeneration preserves them (tracked separately).

## Enabling on your build

Define a user-settings header (see `IDE/C2000/user_settings.h` for a
minimal CHAR_BIT!=8 config) and build with `WOLFSSL_USER_SETTINGS`. For the SP
math backend on a 16-bit-int target also set `WOLFSSL_SP_MATH`,
`SP_WORD_SIZE 32`, and `WOLFSSL_SP_ALLOW_16BIT_CPU`.

## Reference example

A complete bare-metal example with KATs, benchmark, linker scripts, and per-
algorithm build toggles is in wolfSSL Examples:
`embedded/ti-c2000-f28p55x/` (see its `README.md` for the `make` options:
`ECC`, `MLKEM`, `AES`, `AESEXTRA`, `X25519`, `HKDF`, `CHACHA`, `RSA`, `SIGN`,
`BENCH`).

Representative throughput on the F28P55X at 150 MHz: SHA-256 ~284 KiB/s; SHA3-256
~264 KiB/s; SHAKE128 ~319 KiB/s; RNG Hash-DRBG ~122 KiB/s. ML-DSA-87 verify
~225 ms/op in ~10.7 KB RAM (zero heap, with `WOLFSSL_MLDSA_VERIFY_SMALLEST_MEM`
+ `WOLFSSL_MLDSA_ASSIGN_KEY`).

## Continuous integration

`IDE/C2000/compile.sh` runs `cl2000 --compile_only` over the
`CHAR_BIT != 8` wolfCrypt subset to guard these paths without hardware;
`.github/workflows/ti-c2000-compile.yml` runs it in CI (it fetches/caches the
TI C2000 code generation tools).
68 changes: 68 additions & 0 deletions IDE/C2000/compile.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#!/bin/sh
# compile.sh - compile-only guard for the TI C2000 (C28x, CHAR_BIT==16) port.
#
# Builds the wolfCrypt subset that compiles under CHAR_BIT==16 with the TI cl2000
# code generation tools, using IDE/C2000/user_settings.h. No linking, no
# C2000Ware, no hardware: this only catches compile regressions in the
# CHAR_BIT != 8 gated code paths (SHA-2/3/SHAKE, ML-DSA-87 verify, SP-ECC).
#
# Usage:
# CGT_ROOT=/path/to/ti-cgt-c2000_xx.y.z IDE/C2000/compile.sh
#
# CGT_ROOT must point at a TI C2000 codegen install (the dir containing
# bin/cl2000). The CGT is a free download from TI; in CI it is fetched/cached
# by .github/workflows/ti-c2000-compile.yml.

set -e

: "${CGT_ROOT:?set CGT_ROOT to the ti-cgt-c2000 install (dir with bin/cl2000)}"

# Repo root = two levels up from this script.
SELF_DIR=$(cd "$(dirname "$0")" && pwd)
WOLFROOT=$(cd "$SELF_DIR/../.." && pwd)
CL="$CGT_ROOT/bin/cl2000"

if [ ! -x "$CL" ]; then
echo "ERROR: cl2000 not found/executable at $CL" >&2
exit 2
fi

OUT=$(mktemp -d)
trap 'rm -rf "$OUT"' EXIT

INCS="-I$CGT_ROOT/include -I$WOLFROOT -I$SELF_DIR"
CFLAGS="-v28 --abi=eabi --float_support=fpu32 --tmu_support=tmu1 -O2 \
--define=WOLFSSL_USER_SETTINGS --display_error_number --diag_warning=225"

# wolfCrypt sources to compile-guard under CHAR_BIT==16. This is the set that
# carries the CHAR_BIT != 8 gated fixes (plus their direct deps) - the
# regression surface for this port. hash.c (an unmodified dispatch wrapper) is
# intentionally omitted: its wc_OidGetHash() OID switch needs the fuller ASN/OID
# config of a real build to avoid a 16-bit-int case-label fold, and it is
# covered by the on-target example build, not by this minimal guard.
SRCS="error wc_port memory logging misc coding \
sha sha256 sha512 sha3 wc_mldsa random ecc sp_int sp_c32 \
aes cmac chacha poly1305 \
curve25519 ed25519 fe_operations ge_operations \
curve448 ed448 fe_448 ge_448"

rc=0
for s in $SRCS; do
printf 'CC %s.c ... ' "$s"
if "$CL" $CFLAGS $INCS --compile_only --skip_assembler \
--asm_directory="$OUT" --obj_directory="$OUT" \
"$WOLFROOT/wolfcrypt/src/$s.c" > "$OUT/$s.log" 2>&1; then
echo "ok"
else
echo "FAIL"
cat "$OUT/$s.log"
rc=1
fi
done

if [ "$rc" -eq 0 ]; then
echo "TI C2000 compile-only guard: PASS"
else
echo "TI C2000 compile-only guard: FAIL" >&2
fi
exit "$rc"
111 changes: 111 additions & 0 deletions IDE/C2000/user_settings.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/* user_settings.h - minimal wolfCrypt config for the TI C2000 (C28x,
* CHAR_BIT==16) compile-only CI guard.
*
* This is NOT a board config: it has no BSP/device dependencies. Its only job
* is to enable the wolfCrypt subset that carries the CHAR_BIT != 8 gated code
* (SHA-1/2/3/SHAKE, ML-DSA-87 verify, ECDSA/ECDH P-256 via SP math, AES and its
* modes, ChaCha20-Poly1305, X25519/Ed25519, X448/Ed448) so that
* IDE/C2000/compile.sh can compile them with cl2000 and catch regressions.
* cl2000 predefines __TMS320C28XX__, so types.h auto-enables WOLFSSL_WIDE_BYTE;
* we do not set it here. */
#ifndef TI_C2000_CI_USER_SETTINGS_H
#define TI_C2000_CI_USER_SETTINGS_H

#define WOLFCRYPT_ONLY /* crypto only - no TLS (no MD5/SHA1 dep) */
#define WOLFSSL_GENERAL_ALIGNMENT 2
#define HAVE_LIMITS_H
#define WOLFSSL_NO_ASM
#define NO_INLINE
#define SINGLE_THREADED
#define NO_FILESYSTEM
#define NO_WOLFSSL_DIR
#define NO_MAIN_DRIVER
#define NO_DEV_RANDOM
#define WOLFSSL_IGNORE_FILE_WARN
#define BENCH_EMBEDDED
#define NO_WOLFSSL_MEMORY
#define WOLFSSL_GENSEED_FORTEST /* dev-only seed; no TRNG on this part */

/* Hashes (SHA-1 is on by default - NO_SHA is not set) */
#define WOLFSSL_SHA512
#define WOLFSSL_SHA384
#define WOLFSSL_SHA3
#define WOLFSSL_SHAKE128
#define WOLFSSL_SHAKE256

/* AES + modes (block/key/keystream octet I/O and the XTS tweak carry) */
#define HAVE_AES_CBC
#define HAVE_AES_DECRYPT
#define WOLFSSL_AES_COUNTER
#define WOLFSSL_AES_CFB
#define WOLFSSL_AES_OFB
#define HAVE_AESGCM
#define GCM_SMALL
#define HAVE_AESCCM
#define WOLFSSL_CMAC
#define WOLFSSL_AES_XTS
#define WOLFSSL_AES_SIV
#define WOLFSSL_AES_EAX
#define WOLFSSL_AES_DIRECT

/* ChaCha20-Poly1305 (chunk size, keystream and Poly1305 length octet I/O) */
#define HAVE_CHACHA
#define HAVE_POLY1305

/* Curve25519/Ed25519 + Curve448/Ed448 (field serialization octet I/O). 448
* uses the SMALL byte-array backend (no __uint128_t on this toolchain). */
#define HAVE_CURVE25519
#define HAVE_ED25519
#define HAVE_CURVE448
#define CURVE448_SMALL
#define HAVE_ED448
#define ED448_SMALL

/* ML-DSA-87 verify (smallest-mem streaming verifier) */
#define WOLFSSL_HAVE_MLDSA
#define WOLFSSL_NO_ML_DSA_44
#define WOLFSSL_NO_ML_DSA_65
#define WOLFSSL_MLDSA_NO_ASN1
#define WOLFSSL_MLDSA_VERIFY_ONLY
#define WOLFSSL_MLDSA_VERIFY_SMALL_MEM
#define WOLFSSL_MLDSA_VERIFY_NO_MALLOC
#define WOLFSSL_MLDSA_VERIFY_SMALLEST_MEM
#undef WOLFSSL_MLDSA_ALIGNMENT
#define WOLFSSL_MLDSA_ALIGNMENT 16
#define WOLFSSL_SMALL_STACK

/* ECDSA / ECDH P-256 via SP single-precision math (sp_c32.c) */
#define HAVE_ECC
#define ECC_USER_CURVES
#define HAVE_ECC256
#define HAVE_ECC_VERIFY
#define HAVE_ECC_SIGN
#define HAVE_ECC_DHE
#define ECC_TIMING_RESISTANT
#define WOLFSSL_SP_MATH
#define WOLFSSL_HAVE_SP_ECC
#define WOLFSSL_SP_NO_MALLOC
#define WOLFSSL_SP_SMALL
#define SP_WORD_SIZE 32
#define WOLFSSL_SP_ALLOW_16BIT_CPU

/* Off: big-int/ASN and legacy algorithms not part of the CHAR_BIT != 8 surface.
* (RSA/DH are validated on hardware but their CHAR_BIT != 8 fixes live in
* sp_int.c/sp_c32.c, already compiled here via ECC.) */
#define NO_RSA
#define NO_DH
#define NO_DSA
#define NO_ASN
#define NO_CERTS
#define NO_PWDBASED
#define NO_PKCS7
#define NO_PKCS12
#define NO_SIG_WRAPPER
#define NO_DES3
#define NO_RC4
#define NO_MD4
#define NO_MD5
#define NO_ASN_TIME
#define WOLFSSL_USER_CURRTIME

#endif /* TI_C2000_CI_USER_SETTINGS_H */
1 change: 1 addition & 0 deletions IDE/include.am
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ include IDE/XCODE/include.am
include IDE/XilinxSDK/include.am
include IDE/zephyr/include.am

EXTRA_DIST+= IDE/C2000
EXTRA_DIST+= IDE/Espressif
EXTRA_DIST+= IDE/HEXIWEAR
EXTRA_DIST+= IDE/IAR-EWARM
Expand Down
Loading