diff --git a/embedded/ti-c2000-f28p55x/.gitignore b/embedded/ti-c2000-f28p55x/.gitignore new file mode 100644 index 000000000..586061447 --- /dev/null +++ b/embedded/ti-c2000-f28p55x/.gitignore @@ -0,0 +1,2 @@ +out/ +*.obj diff --git a/embedded/ti-c2000-f28p55x/28p55x_wolf_flash_lnk.cmd b/embedded/ti-c2000-f28p55x/28p55x_wolf_flash_lnk.cmd new file mode 100644 index 000000000..56c7e5523 --- /dev/null +++ b/embedded/ti-c2000-f28p55x/28p55x_wolf_flash_lnk.cmd @@ -0,0 +1,89 @@ +/* 28p55x_wolf_flash_lnk.cmd + * + * Linker command file for the wolfCrypt test/benchmark on the + * TI LAUNCHXL-F28P55X (TMS320F28P550SJ), running from flash. EABI only + * (build driverlib and this project with --abi=eabi). + * + * Differs from the stock C2000Ware generic flash linker in three ways that + * the ML-DSA-87 verify path requires: + * - A large STACK in low RAM. The C28x stack pointer is 16-bit, so the + * stack must live below 0x10000. RAMLS0-7 (0x8000..0xBFFF, 16 KW) is the + * largest contiguous low block; the verify key struct (~7 KW pinned by + * WOLFSSL_MLDSA_VERIFY_NO_MALLOC) plus Keccak frames live here. + * - A real heap (.sysmem) in low RAMGS0-1 for the test/benchmark malloc + * temporaries (ML-DSA verify itself allocates nothing). + * - .bss/.data placed in the high RAMGS2-3 + RAMLS8-9 blocks so they do not + * compete with the stack for low RAM. + * + * Copyright (C) 2006-2026 wolfSSL Inc. GPLv3 - see project headers. + */ + +-stack 0x4000 /* 16 KW C28x stack (full RAMLS0-7); wolfcrypt_test's deep call + * chain + SHAKE/large-hash locals (~1.6 KW) need the headroom */ +-heap 0x2000 /* 8 KW heap (RAMGS1); RAMGS0 now hosts RAM-resident hot code. + * ML-DSA verify uses no heap; test/benchmark temporaries fit. */ + +MEMORY +{ + BEGIN : origin = 0x080000, length = 0x000002 + + BOOT_RSVD : origin = 0x000002, length = 0x000126 /* M0, used by boot ROM stack */ + RAMM0 : origin = 0x000128, length = 0x0002D8 + RAMM1 : origin = 0x000400, length = 0x000400 + + /* Low RAM (< 0x10000): usable for the 16-bit-SP stack and the heap. */ + RAMLS_STACK : origin = 0x008000, length = 0x004000 /* RAMLS0-7, 16 KW */ + /* RAMGS0 hosts RAM-resident hot code (.TI.ramfunc), RAMGS1 the heap. At + * 150 MHz the flash has wait states; running the Keccak permutation and the + * ML-DSA NTTs from RAM removes the instruction-fetch stalls. */ + RAMGS_RAMCODE : origin = 0x00C000, length = 0x002000 /* RAMGS0, 8 KW */ + RAMGS_HEAP : origin = 0x00E000, length = 0x002000 /* RAMGS1, 8 KW */ + + /* High RAM (>= 0x10000): data only (no stack). */ + RAMGS_HI : origin = 0x010000, length = 0x004000 /* RAMGS2-3, 16 KW */ + RAMLS_HI : origin = 0x014000, length = 0x004000 /* RAMLS8-9, 16 KW */ + + /* Flash banks (ML-DSA verify code + const test vectors are large). */ + FLASH_BANK0 : origin = 0x080002, length = 0x01FFFE + FLASH_BANK1 : origin = 0x0A0000, length = 0x020000 + FLASH_BANK2 : origin = 0x0C0000, length = 0x020000 + FLASH_BANK3 : origin = 0x0E0000, length = 0x020000 + FLASH_BANK4 : origin = 0x100000, length = 0x008000 + + RESET : origin = 0x3FFFC0, length = 0x000002 +} + +SECTIONS +{ + codestart : > BEGIN + /* Hot crypto relocated to RAM (loaded from flash, copied by Device_init's + * Ramfuncs memcpy). Listed before .text so these subsections are claimed + * here, not by the generic .text below. --gen_func_subsections=on makes + * each function its own .text: input section. */ + .TI.ramfunc : { sha3.obj(.text:BlockSha3) + wc_mldsa.obj(.text:mldsa_ntt_c) + wc_mldsa.obj(.text:mldsa_invntt_c) + wc_mldsa.obj(.text:mldsa_ntt_small_c) } + LOAD = FLASH_BANK0, + RUN = RAMGS_RAMCODE, + LOAD_START(RamfuncsLoadStart), + LOAD_SIZE(RamfuncsLoadSize), + LOAD_END(RamfuncsLoadEnd), + RUN_START(RamfuncsRunStart), + RUN_SIZE(RamfuncsRunSize), + RUN_END(RamfuncsRunEnd), + ALIGN(8) + .text : >> FLASH_BANK0 | FLASH_BANK1 | FLASH_BANK2 | FLASH_BANK3, ALIGN(8) + .cinit : > FLASH_BANK0, ALIGN(8) + .switch : > FLASH_BANK0, ALIGN(8) + .reset : > RESET, TYPE = DSECT /* unused */ + + .stack : > RAMLS_STACK + + .bss : >> RAMGS_HI | RAMLS_HI + .bss:output : > RAMGS_HI + .init_array : > FLASH_BANK0, ALIGN(8) + .const : >> FLASH_BANK0 | FLASH_BANK1, ALIGN(8) + .data : >> RAMGS_HI | RAMLS_HI + .sysmem : > RAMGS_HEAP +} diff --git a/embedded/ti-c2000-f28p55x/28p55x_wolf_sign_lnk.cmd b/embedded/ti-c2000-f28p55x/28p55x_wolf_sign_lnk.cmd new file mode 100644 index 000000000..91c1fccb8 --- /dev/null +++ b/embedded/ti-c2000-f28p55x/28p55x_wolf_sign_lnk.cmd @@ -0,0 +1,75 @@ +/* 28p55x_wolf_sign_lnk.cmd + * + * Linker command file for the FULL ML-DSA-87 (keygen + sign + verify) build of + * the wolfCrypt example on the TI LAUNCHXL-F28P55X (TMS320F28P550SJ), running + * from flash. EABI only. Selected by `make SIGN=1`. + * + * ML-DSA-87 keygen/sign/verify need a much larger heap than the verify-only + * build. Even with every small-memory path enabled the peak is ~30 KW in a + * single allocation, so this script dedicates the whole contiguous RAMGS0-3 + * block (32 KW) to the heap (.sysmem). The stack stays in low RAMLS0-7 (the + * 16-bit SP needs RAM < 0x10000) and .bss/.data live in RAMLS8-9. The full + * wolfcrypt test/benchmark are NOT built in this mode (they would not fit + * alongside the 32 KW heap), so .bss is small. + * + * Copyright (C) 2006-2026 wolfSSL Inc. GPLv3 - see project headers. + */ + +-stack 0x3000 /* 12 KW C28x stack (< 0x10000); big arrays go to heap via + * WOLFSSL_SMALL_STACK */ +-heap 0x7E00 /* ~31.5 KW heap - ML-DSA-87 keygen/sign peak ~30.5 KW */ + +MEMORY +{ + BEGIN : origin = 0x080000, length = 0x000002 + + BOOT_RSVD : origin = 0x000002, length = 0x000126 /* M0, used by boot ROM stack */ + RAMM0 : origin = 0x000128, length = 0x0002D8 + RAMM1 : origin = 0x000400, length = 0x000400 + + /* Low RAM (< 0x10000): the 16-bit-SP stack. */ + RAMLS_STACK : origin = 0x008000, length = 0x004000 /* RAMLS0-7, 16 KW */ + + /* RAMGS0-3 is one contiguous 32 KW block (0xC000..0x13FFF): the heap. */ + RAMGS_BIG : origin = 0x00C000, length = 0x008000 /* RAMGS0-3, 32 KW */ + + /* High RAM: .bss/.data (no stack here). */ + RAMLS_HI : origin = 0x014000, length = 0x004000 /* RAMLS8-9, 16 KW */ + + /* Flash banks (ML-DSA sign code is large). */ + FLASH_BANK0 : origin = 0x080002, length = 0x01FFFE + FLASH_BANK1 : origin = 0x0A0000, length = 0x020000 + FLASH_BANK2 : origin = 0x0C0000, length = 0x020000 + FLASH_BANK3 : origin = 0x0E0000, length = 0x020000 + FLASH_BANK4 : origin = 0x100000, length = 0x008000 + + RESET : origin = 0x3FFFC0, length = 0x000002 +} + +SECTIONS +{ + codestart : > BEGIN + .text : >> FLASH_BANK0 | FLASH_BANK1 | FLASH_BANK2 | FLASH_BANK3, ALIGN(8) + .cinit : > FLASH_BANK0, ALIGN(8) + .switch : > FLASH_BANK0, ALIGN(8) + .reset : > RESET, TYPE = DSECT /* unused */ + + .stack : > RAMLS_STACK + + .bss : > RAMLS_HI + .bss:output : > RAMLS_HI + .init_array : > FLASH_BANK0, ALIGN(8) + .const : >> FLASH_BANK0 | FLASH_BANK1, ALIGN(8) + .data : > RAMLS_HI + .sysmem : > RAMGS_BIG + + .TI.ramfunc : {} LOAD = FLASH_BANK0, + RUN = RAMM0, + LOAD_START(RamfuncsLoadStart), + LOAD_SIZE(RamfuncsLoadSize), + LOAD_END(RamfuncsLoadEnd), + RUN_START(RamfuncsRunStart), + RUN_SIZE(RamfuncsRunSize), + RUN_END(RamfuncsRunEnd), + ALIGN(8) +} diff --git a/embedded/ti-c2000-f28p55x/Header/user_settings.h b/embedded/ti-c2000-f28p55x/Header/user_settings.h new file mode 100644 index 000000000..fd5ed445c --- /dev/null +++ b/embedded/ti-c2000-f28p55x/Header/user_settings.h @@ -0,0 +1,339 @@ +/* user_settings.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 + */ + +/* wolfSSL user settings for the TI C2000 C28x DSP (LAUNCHXL-F28P55X). + * + * IMPORTANT - this is a SCOPED build for a new architecture bring-up: + * - The C28x has 16-bit bytes (CHAR_BIT == 16). wolfSSL's byte-packing + * code assumes 8-bit octets, so this build is deliberately limited to the + * algorithms whose correctness we validate with known-answer tests: + * SHA-256, SHA-384/512, SHA3, SHAKE128/256, and ML-DSA-87 verify only. + * - RSA / ECC / DH / TFM / SP-bignum are NOT built, which avoids the + * big-integer code paths most sensitive to the 16-bit-byte layout. + * - The device has no hardware TRNG and no SHA3 accelerator; everything here + * is portable C software crypto. ML-DSA verify is deterministic and uses + * no entropy. The RNG stub below is for benchmark/test wiring ONLY and is + * NOT cryptographically secure - do not ship it. + */ + +#ifndef WOLFSSL_USER_SETTINGS_C2000_H +#define WOLFSSL_USER_SETTINGS_C2000_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* ------------------------------------------------------------------------- */ +/* Platform / C28x toolchain */ +/* ------------------------------------------------------------------------- */ +#undef SINGLE_THREADED +#define SINGLE_THREADED + +#undef WOLFCRYPT_ONLY /* crypto only, no TLS layer */ +#define WOLFCRYPT_ONLY + +#undef NO_FILESYSTEM +#define NO_FILESYSTEM + +#undef NO_WRITEV +#define NO_WRITEV + +#undef NO_MAIN_DRIVER /* our main() lives in wolf_main.c */ +#define NO_MAIN_DRIVER + +#undef NO_DEV_RANDOM +#define NO_DEV_RANDOM + +#undef NO_SESSION_CACHE +#define NO_SESSION_CACHE + +#undef WOLFSSL_IGNORE_FILE_WARN +#define WOLFSSL_IGNORE_FILE_WARN + +#undef BENCH_EMBEDDED /* reduced benchmark sizes for an MCU */ +#define BENCH_EMBEDDED + +/* C28x integer widths: char/short/int = 16-bit, long = 32-bit, + * long long = 64-bit. wolfCrypt needs a true 64-bit word for SHA3/SHA-512 + * and ML-DSA, which long long provides. */ +#undef SIZEOF_LONG +#define SIZEOF_LONG 4 +#undef SIZEOF_LONG_LONG +#define SIZEOF_LONG_LONG 8 + +/* Pull in the toolchain's so CHAR_BIT is the real value (16 on + * C28x) instead of wolfSSL's 8-bit fallback, and so UINT_MAX reflects the + * 16-bit int. This is critical for correct byte math. */ +#undef HAVE_LIMITS_H +#define HAVE_LIMITS_H + +/* C28x has 16-bit int. WC_16BIT_CPU makes wolfSSL use the correct integer + * widths (word16 = unsigned int = 16-bit, word32 = unsigned long = 32-bit); + * without it wolfSSL assumes int is 32-bit and word32 comes out only 16 bits, + * silently truncating all 32-bit crypto math. C28x also has a native 64-bit + * long long, so WORD64_AVAILABLE is preserved via the SIZEOF_LONG_LONG==8 + * guard added to types.h (for SHA-512/SHA-3/ML-DSA). */ +#undef WC_16BIT_CPU +#define WC_16BIT_CPU + +/* The C28x is little-endian. Leave BIG_ENDIAN_ORDER undefined so the default + * little-endian path is used. (Verify on hardware with the SHA KATs.) */ + +/* CHAR_BIT==16 portability levers (see README "16-bit byte" section): + * ML-DSA bit-packing has fast paths that cast a byte buffer to word32/word64 + * (gated on WOLFSSL_MLDSA_ALIGNMENT <= 2/4/8). On a 16-bit-byte machine a + * wordN spans N/2 cells, not N octets, so every such cast is wrong. Force + * the fully portable byte-by-byte path by making the alignment exceed all + * the gates (max gate is <= 8). + * The Keccak state-aliasing hazard (xorbuf/memcpy over the word64 state) is + * handled by the gated octet-wise SHA3 path in sha3.c (WC_SHA3_BYTEWISE). */ +#undef WOLFSSL_GENERAL_ALIGNMENT +#define WOLFSSL_GENERAL_ALIGNMENT 2 +#undef WOLFSSL_MLDSA_ALIGNMENT +#define WOLFSSL_MLDSA_ALIGNMENT 16 + +/* Force portable C cores - no x86/ARM assembly. */ +#undef WOLFSSL_NO_ASM +#define WOLFSSL_NO_ASM +#undef WC_SHA3_NO_ASM +#define WC_SHA3_NO_ASM + +/* Compile misc.c as its own translation unit (extern, not inline). The TI + * CGT treats a plain `inline` definition as a C99 extern-inline and emits no + * out-of-line copy, so the inline-misc path leaves xorbuf/ByteReverseWords64 + * unresolved at link. NO_INLINE makes them ordinary extern functions; the + * build compiles wolfcrypt/src/misc.c once. */ +#undef NO_INLINE +#define NO_INLINE + +/* ------------------------------------------------------------------------- */ +/* Hashing - the scoped subset */ +/* ------------------------------------------------------------------------- */ +/* SHA-256/224 are on by default (NO_SHA256 not defined). */ + +#undef WOLFSSL_SHA512 +#define WOLFSSL_SHA512 +#undef WOLFSSL_SHA384 +#define WOLFSSL_SHA384 + +#undef WOLFSSL_SHA3 +#define WOLFSSL_SHA3 +#undef WOLFSSL_SHAKE128 +#define WOLFSSL_SHAKE128 +#undef WOLFSSL_SHAKE256 +#define WOLFSSL_SHAKE256 + +/* ------------------------------------------------------------------------- */ +/* ML-DSA-87 (Dilithium L5) - VERIFY ONLY */ +/* ------------------------------------------------------------------------- */ +#undef WOLFSSL_HAVE_MLDSA +#define WOLFSSL_HAVE_MLDSA + +/* Build only ML-DSA-87 (level 5). */ +#undef WOLFSSL_NO_ML_DSA_44 +#define WOLFSSL_NO_ML_DSA_44 +#undef WOLFSSL_NO_ML_DSA_65 +#define WOLFSSL_NO_ML_DSA_65 + +/* Raw key/sig import - no ASN.1 (both modes). */ +#undef WOLFSSL_MLDSA_NO_ASN1 +#define WOLFSSL_MLDSA_NO_ASN1 + +#ifdef WOLF_MLDSA_SIGN +/* Full ML-DSA-87 (keygen + sign + verify). Build with `make SIGN=1`. ML-DSA-87 + * keygen/sign/verify need a large working set; enabling EVERY small-memory path + * brings the peak heap to ~30 KW (measured on host), which fits the C28x when + * the sign linker script gives .sysmem the RAMGS0-3 block. NOTE: the dev RNG + * stub below is NOT secure - real signing needs a true TRNG. */ +#undef WOLFSSL_MLDSA_MAKE_KEY_SMALL_MEM +#define WOLFSSL_MLDSA_MAKE_KEY_SMALL_MEM +#undef WOLFSSL_MLDSA_SIGN_SMALL_MEM +#define WOLFSSL_MLDSA_SIGN_SMALL_MEM +#undef WOLFSSL_MLDSA_VERIFY_SMALL_MEM +#define WOLFSSL_MLDSA_VERIFY_SMALL_MEM +#undef WOLFSSL_MLDSA_SMALL_MEM_POLY64 +#define WOLFSSL_MLDSA_SMALL_MEM_POLY64 +/* ML-DSA-87 sign/keygen put large polynomial arrays on the stack by default, + * which overflows the C28x's low-RAM (< 0x10000) stack. WOLFSSL_SMALL_STACK + * moves those to the heap (sized by the sign linker for ~31 KW peak). */ +#undef WOLFSSL_SMALL_STACK +#define WOLFSSL_SMALL_STACK +#else +/* Verify path only (auto-derives NO_MAKE_KEY + NO_SIGN + public-key-only), + * with the small-memory streaming verifier and no heap (buffers pinned into + * the key struct). */ +#undef WOLFSSL_MLDSA_VERIFY_ONLY +#define WOLFSSL_MLDSA_VERIFY_ONLY +#undef WOLFSSL_MLDSA_VERIFY_SMALL_MEM +#define WOLFSSL_MLDSA_VERIFY_SMALL_MEM +#undef WOLFSSL_MLDSA_VERIFY_NO_MALLOC +#define WOLFSSL_MLDSA_VERIFY_NO_MALLOC +/* Smallest verify RAM: stream the signature's z vector one polynomial at a + * 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 +#define WOLFSSL_MLDSA_VERIFY_SMALLEST_MEM +/* 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 + * a 5,184-byte byte[] on the 16-bit-cell C28x), bringing ML-DSA-87 verify to + * ~10.7 KB total RAM. Left off by default because the caller must keep the + * public-key buffer valid for the key's lifetime. */ +#endif + +/* ------------------------------------------------------------------------- */ +/* Disabled: big-integer / asymmetric (keeps TFM/ECC/integer out of build) */ +/* ------------------------------------------------------------------------- */ +#ifdef WOLF_ECC +/* ------------------------------------------------------------------------- */ +/* ECC P-256 (SECP256R1) via SP single-precision math (sp_c32.c), no malloc. */ +/* Enabled with EXTRA_CFLAGS=--define=WOLF_ECC (ECC=1 build). Covers ECDSA */ +/* keygen/sign/verify and ECDH. Uses raw mp_int (sign/verify _ex) APIs so no */ +/* ASN/DER is required for bring-up. */ +/* ------------------------------------------------------------------------- */ +#undef HAVE_ECC +#define HAVE_ECC +#undef ECC_USER_CURVES /* build only the curves we name (just P-256) */ +#define ECC_USER_CURVES +#undef HAVE_ECC256 +#define HAVE_ECC256 +#undef HAVE_ECC_VERIFY +#define HAVE_ECC_VERIFY +#undef HAVE_ECC_SIGN +#define HAVE_ECC_SIGN +#undef HAVE_ECC_DHE /* ECDH shared secret */ +#define HAVE_ECC_DHE +#undef ECC_TIMING_RESISTANT +#define ECC_TIMING_RESISTANT +/* SP single-precision P-256 backend (32-bit limbs in sp_c32.c). */ +#undef WOLFSSL_SP_MATH +#define WOLFSSL_SP_MATH +#undef WOLFSSL_HAVE_SP_ECC +#define WOLFSSL_HAVE_SP_ECC +#undef WOLFSSL_SP_NO_MALLOC +#define WOLFSSL_SP_NO_MALLOC +#undef WOLFSSL_SP_SMALL +#define WOLFSSL_SP_SMALL +#undef SP_WORD_SIZE +#define SP_WORD_SIZE 32 +/* C28x int is 16-bit (WC_16BIT_CPU) but we use 32-bit SP digits + octet-wise + * byte I/O, so opt past the conservative SP-vs-16-bit guard. */ +#undef WOLFSSL_SP_ALLOW_16BIT_CPU +#define WOLFSSL_SP_ALLOW_16BIT_CPU +/* NO_BIG_INT stays off: SP provides the mp_int interface. */ +#else +/* No multi-precision integer math at all (no SP/TFM/integer.c). ML-DSA verify + * and the hashes use no mp_int, and this avoids the SP-math vs WC_16BIT_CPU + * conflict. */ +#undef NO_BIG_INT +#define NO_BIG_INT +#endif /* WOLF_ECC */ + +#undef NO_RSA +#define NO_RSA +#undef NO_DH +#define NO_DH +#undef NO_DSA +#define NO_DSA +#ifndef WOLF_ECC +/* HAVE_ECC intentionally not defined - no ECC. */ +#endif +#undef WOLFSSL_HAVE_MLKEM /* no ML-KEM this pass */ +#undef NO_ASN +#define NO_ASN /* ML-DSA + ECC raw import; no asn.c needed */ +#undef NO_CERTS +#define NO_CERTS +#undef NO_PWDBASED +#define NO_PWDBASED +#undef NO_PKCS7 +#define NO_PKCS7 +#undef NO_PKCS12 +#define NO_PKCS12 +#undef NO_SIG_WRAPPER +#define NO_SIG_WRAPPER + +/* ------------------------------------------------------------------------- */ +/* Disabled: unused symmetric / legacy (shrink the first build) */ +/* ------------------------------------------------------------------------- */ +#undef NO_AES /* AES accelerator support is a later phase */ +#define NO_AES +#undef NO_DES3 +#define NO_DES3 +#undef NO_RC4 +#define NO_RC4 +#undef NO_MD4 +#define NO_MD4 +#undef NO_MD5 +#define NO_MD5 +#undef NO_SHA /* SHA-1 not in scope */ +#define NO_SHA +#undef NO_HMAC /* relax if the harness needs it */ +#define NO_HMAC + +/* ------------------------------------------------------------------------- */ +/* Memory */ +/* ------------------------------------------------------------------------- */ +/* Use the TI runtime heap (malloc/free) for test/benchmark temporaries. + * ML-DSA verify itself allocates nothing (WOLFSSL_MLDSA_VERIFY_NO_MALLOC). + * NO_WOLFSSL_MEMORY routes XMALLOC straight to malloc/free with no wrapper. */ +#undef NO_WOLFSSL_MEMORY +#define NO_WOLFSSL_MEMORY + +/* ------------------------------------------------------------------------- */ +/* Time - benchmark elapsed time comes from a CPU timer (wolf_main.c) */ +/* ------------------------------------------------------------------------- */ +#undef NO_ASN_TIME +#define NO_ASN_TIME + +#undef WOLFSSL_USER_CURRTIME /* benchmark.c uses our current_time() */ +#define WOLFSSL_USER_CURRTIME + +/* XTIME stub - hashing and ML-DSA verify never use wall-clock time. Define + * XTIME directly (not TIME_OVERRIDES) so wolfSSL leaves ours in place and + * defaults XGMTIME on its own (nothing in this scoped build calls XGMTIME). */ +extern long my_time(long* t); +#undef XTIME +#define XTIME(tl) my_time((tl)) + +/* ------------------------------------------------------------------------- */ +/* 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. */ +#undef WOLFSSL_GENSEED_FORTEST +#define WOLFSSL_GENSEED_FORTEST + +/* 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 + * before the SHA/SHAKE/ML-DSA KATs run. */ +#undef TEST_ALWAYS_RUN_TO_END +#define TEST_ALWAYS_RUN_TO_END + +#ifdef __cplusplus +} +#endif + +#endif /* WOLFSSL_USER_SETTINGS_C2000_H */ diff --git a/embedded/ti-c2000-f28p55x/Makefile b/embedded/ti-c2000-f28p55x/Makefile new file mode 100644 index 000000000..842e81457 --- /dev/null +++ b/embedded/ti-c2000-f28p55x/Makefile @@ -0,0 +1,150 @@ +# Makefile - headless wolfCrypt test/benchmark build for TI LAUNCHXL-F28P55X +# (TMS320F28P550SJ, C2000 C28x DSP), built from flash with cl2000. +# +# Copyright (C) 2006-2026 wolfSSL Inc. GPLv3 - see project headers. +# +# Usage: +# make CGT_ROOT=/path/to/ti-cgt-c2000_xx.y.z [C2000WARE=/path/to/C2000Ware] +# +# CGT_ROOT must point at a TI C2000 codegen install (the dir containing +# bin/cl2000). It ships with Code Composer Studio or as a standalone package. +# C2000WARE defaults to ~/ti/C2000Ware_26_01_00_00. +# +# This is the SCOPED bring-up build: SHA-2, SHA-3/SHAKE, and ML-DSA-87 verify +# only. See README.md. + +CGT_ROOT ?= +C2000WARE ?= $(HOME)/ti/C2000Ware_26_01_00_00 + +# wolfSSL source tree (this example lives in wolfssl-examples; point WOLFROOT +# at a wolfSSL checkout that has the CHAR_BIT!=8 fixes). Override on the +# command line, e.g. make WOLFROOT=/path/to/wolfssl. +WOLFROOT ?= $(abspath $(CURDIR)/../../../wolfssl-alt) + +DEV := $(C2000WARE)/device_support/f28p55x +DRV := $(C2000WARE)/driverlib/f28p55x/driverlib +DRVLIB := $(DRV)/ccs/Release + +OUT := out +TARGET := $(OUT)/wolfcrypt_f28p55x.out +MAP := $(OUT)/wolfcrypt_f28p55x.map + +ifeq ($(CGT_ROOT),) +$(error Set CGT_ROOT to your TI C2000 codegen install, e.g. \ + make CGT_ROOT=$(HOME)/ti/ccs/tools/compiler/ti-cgt-c2000_22.6.2.LTS) +endif + +CL := $(CGT_ROOT)/bin/cl2000 + +INCS := \ + -I$(CGT_ROOT)/include \ + -I$(DRV) \ + -I$(DEV)/common/include \ + -I$(DEV)/headers/include \ + -I$(WOLFROOT) \ + -I$(CURDIR)/Header + +# --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 +# use the CCS console (CIO over JTAG) for first light. +CFLAGS := \ + -v28 --float_support=fpu32 --tmu_support=tmu1 --abi=eabi \ + -O2 \ + --define=_LAUNCHXL_F28P55X \ + --define=_FLASH \ + --define=WOLFSSL_USER_SETTINGS \ + --gen_func_subsections=on \ + --diag_warning=225 --display_error_number \ + $(EXTRA_CFLAGS) \ + $(INCS) + +LFLAGS := \ + --reread_libs --warn_sections \ + -i$(CGT_ROOT)/lib -i$(DRVLIB) \ + -m $(MAP) + +# wolfCrypt source subset (the only files that compile under CHAR_BIT==16). +WC_SRCS := \ + $(WOLFROOT)/wolfcrypt/src/error.c \ + $(WOLFROOT)/wolfcrypt/src/wc_port.c \ + $(WOLFROOT)/wolfcrypt/src/memory.c \ + $(WOLFROOT)/wolfcrypt/src/logging.c \ + $(WOLFROOT)/wolfcrypt/src/misc.c \ + $(WOLFROOT)/wolfcrypt/src/coding.c \ + $(WOLFROOT)/wolfcrypt/src/hash.c \ + $(WOLFROOT)/wolfcrypt/src/sha256.c \ + $(WOLFROOT)/wolfcrypt/src/sha512.c \ + $(WOLFROOT)/wolfcrypt/src/sha3.c \ + $(WOLFROOT)/wolfcrypt/src/wc_mldsa.c \ + $(WOLFROOT)/wolfcrypt/src/random.c + +# ECC=1 adds ECDSA/ECDH over SECP256R1 via SP single-precision math. +ECC ?= 0 +ifeq ($(ECC),1) + CFLAGS += --define=WOLF_ECC + WC_SRCS += \ + $(WOLFROOT)/wolfcrypt/src/ecc.c \ + $(WOLFROOT)/wolfcrypt/src/sp_int.c \ + $(WOLFROOT)/wolfcrypt/src/sp_c32.c +endif + +HARNESS_SRCS := \ + $(WOLFROOT)/wolfcrypt/test/test.c \ + $(WOLFROOT)/wolfcrypt/benchmark/benchmark.c + +BSP_SRCS := \ + $(CURDIR)/Source/wolf_main.c \ + $(DEV)/common/source/device.c + +ASM_SRCS := \ + $(DEV)/common/source/f28p55x_codestartbranch.asm + +# SIGN=1 builds the full ML-DSA-87 (keygen + sign + verify) demo. It needs a +# 32 KW heap, so the wolfcrypt test/benchmark harness is left out and a +# dedicated linker script is used. Default (SIGN=0) is the verify-only build +# with the full test/benchmark harness. +SIGN ?= 0 +# BENCH=1 runs ONLY the benchmark (skips wolfcrypt_test). wolfcrypt_test's +# heap high-water leaves too little for the benchmark's block buffers on this +# RAM-limited part, so run them in separate images: default = KATs + test, and +# BENCH=1 = KATs + benchmark. +BENCH ?= 0 +ifeq ($(SIGN),1) + CFLAGS += --define=WOLF_MLDSA_SIGN --define=NO_CRYPT_TEST \ + --define=NO_CRYPT_BENCHMARK + LNKCMD := $(CURDIR)/28p55x_wolf_sign_lnk.cmd + HARNESS_SRCS := +else + LNKCMD := $(CURDIR)/28p55x_wolf_flash_lnk.cmd + ifeq ($(BENCH),1) + CFLAGS += --define=NO_CRYPT_TEST + endif +endif + +ALL_SRCS := $(WC_SRCS) $(HARNESS_SRCS) $(BSP_SRCS) $(ASM_SRCS) + +.PHONY: all clean + +all: $(TARGET) + +$(TARGET): $(ALL_SRCS) $(LNKCMD) user_settings_dep + @mkdir -p $(OUT) + $(CL) $(CFLAGS) \ + $(ALL_SRCS) \ + -z $(LFLAGS) \ + --output_file=$(TARGET) \ + $(LNKCMD) \ + -l driverlib.lib -l libc.a + +# touch-only dependency so editing user_settings.h forces a rebuild +user_settings_dep: Header/user_settings.h + +# Compile-only guard (no link, no C2000Ware): mirrors the upstream CI job at +# wolfssl/.github/workflows/ti-c2000-compile.yml. Builds the CHAR_BIT!=8 +# wolfCrypt subset with cl2000 to catch regressions locally. +.PHONY: compile-ci +compile-ci: + CGT_ROOT=$(CGT_ROOT) $(WOLFROOT)/scripts/ti-c2000/compile.sh + +clean: + rm -rf $(OUT) *.obj *.map *.asm diff --git a/embedded/ti-c2000-f28p55x/README.md b/embedded/ti-c2000-f28p55x/README.md new file mode 100644 index 000000000..b58de5ca6 --- /dev/null +++ b/embedded/ti-c2000-f28p55x/README.md @@ -0,0 +1,80 @@ +# wolfCrypt on TI C2000 C28x (LAUNCHXL-F28P55X) + +Bare-metal wolfCrypt test/benchmark for the TI LAUNCHXL-F28P55X board (TMS320F28P550SJ, C2000 C28x DSP, 150 MHz, 133 KB RAM, 1088 KB flash). This is a **new-architecture bring-up** and is intentionally scoped. + +## What this build includes + +A deliberately limited algorithm set, validated with known-answer tests: + +- SHA-256 / SHA-224 +- SHA-384 / SHA-512 +- SHA3-224/256/384/512, SHAKE128, SHAKE256 +- **ML-DSA-87 (Dilithium level 5), verify only** + +RSA / ECC / DH / TFM / SP-bignum and most symmetric ciphers are **not** built. See the 16-bit-byte section below for why. + +## The 16-bit-byte issue (read this first) + +The C28x is a word-addressed DSP: **`CHAR_BIT == 16`**. A `char`/`unsigned char` (wolfSSL's `byte`) holds 16 bits, the minimum addressable unit is 16 bits, and `(byte)x` masks to 16 bits, not 8. Most of wolfCrypt assumes 8-bit octets. This build sidesteps the worst of it by: + +- Building only hashing + ML-DSA verify (no bignum), so the `tfm.c`/`ecc.c`/`integer.c` byte-packing paths are never compiled. +- `WOLFSSL_GENERAL_ALIGNMENT 2` (nonzero) selects ML-DSA's byte-by-byte packing path instead of the word-cast path, which is octet-layout dependent and wrong here. +- `WOLFSSL_NO_XOR_OPS` forces the byte-by-byte `xorbuf` used by the Keccak absorb, avoiding the `byte*`->`wolfssl_word*` cast hazard in `misc.c`. + +Correctness of SHA-3/SHAKE and ML-DSA under 16-bit bytes is **not proven** until the KATs pass on hardware. Validate strictly in this order (stop and fix at the first failure): + +1. SHA-256 KAT -- confirms basic byte storage + `XMEMCPY` semantics. +2. SHA-512 KAT. +3. **SHA3-256 + SHAKE256 KAT** -- confirms Keccak lane packing/squeeze. This is **expected to fail before a fix**: `sha3.c` aliases the `word64` state as a raw byte stream (`xorbuf(state,...)`, `((byte*)s)[i] ^= pad`, `XMEMCPY(hash, s, rate)`), which only works when a `word64` is 8 octets in memory. On C28x it is four 16-bit cells. The absorb/pad already have an octet-safe `Load64BitLittleEndian` path (currently gated under `BIG_ENDIAN_ORDER`/`WC_SHA3_FAULT_HARDEN`); the missing piece is a little-endian **octet-wise squeeze** to replace `XMEMCPY(hash, s, rate)` with `hash[k] = (byte)((s[k>>3] >> (8*(k&7))) & 0xFF)` (same for the SHAKE `SqueezeBlocks`/`Final` outputs). Add this behind a `CHAR_BIT != 8` gate so other targets are unaffected. If SHA3/SHAKE is wrong, ML-DSA cannot work; fix here first. +4. ML-DSA-87 verify KAT (consumes SHAKE via `SqueezeBlocks`). + +## Toolchain + +- **C2000Ware** (driverlib + device support). This example assumes `~/ti/C2000Ware_26_01_00_00`; override with `C2000WARE=`. +- **TI C2000 codegen** (`cl2000`, the classic CGT -- not the C2000 Clang compiler for this first bring-up). It ships with Code Composer Studio or as a standalone package. Point `CGT_ROOT` at the dir containing `bin/cl2000`. +- For flashing: **DSLite** (bundled with CCS) or **UniFlash**, driving the onboard XDS110. + +## Build + +Headless, from this directory: + +``` +make CGT_ROOT=/path/to/ti-cgt-c2000_xx.y.z +``` + +Output: `out/wolfcrypt_f28p55x.out` (load image) and `out/wolfcrypt_f28p55x.map`. + +Key compiler flags (see `Makefile`): `-v28 --float_support=fpu32 --abi=eabi`, which must match the prebuilt `driverlib.lib`. The repo root is on the include path so the inline `#include ` in `sha3.c`/`wc_mldsa.c` resolves, and `WOLFSSL_USER_SETTINGS` pulls in `Header/user_settings.h`. + +CCS GUI alternative: create an empty F28P550SJ project, add the wolfCrypt source subset listed in the `Makefile` (`WC_SRCS`), `Source/wolf_main.c`, the device-support `device.c` + `f28p55x_codestartbranch.asm`, link `driverlib.lib`, set the predefines (`_LAUNCHXL_F28P55X`, `_FLASH`, `WOLFSSL_USER_SETTINGS`) and the include paths, and use `28p55x_wolf_flash_lnk.cmd` as the linker command file. + +## Console output + +- **First light (no wiring):** build without `WOLF_C2000_SCI_STDOUT`. `printf` goes to the CCS console via CIO over JTAG. Good for proving crypto before debugging the UART. +- **Headless:** add `--define=WOLF_C2000_SCI_STDOUT`. `stdout` is redirected to **SCIA on GPIO28/29**, the XDS110 virtual COM, at **115200 8N1**. Read it with the `uart-monitor` skill on the XDS110 user-UART `/dev/ttyACM*` (identify by udev `XDS110` match). + +## Flash and run + +Boot-mode switch S3 default (GPIO24 + GPIO32 both high) boots from flash. With CCS DSLite: + +``` +DSLite flash --config=F28P550SJ.ccxml -f -v -e out/wolfcrypt_f28p55x.out +``` + +Generate `F28P550SJ.ccxml` once in CCS (Target Configuration: XDS110 + TMS320F28P550SJ). + +## Memory notes + +- Clock: 150 MHz from the 20 MHz crystal Y2 (`device.h` `DEVICE_SETCLOCK_CFG`), flash `RWAIT=3`. Confirm the Y2 frequency against the board silkscreen. +- The C28x stack pointer is 16-bit, so the stack must live below address `0x10000`. `28p55x_wolf_flash_lnk.cmd` puts a 12 KW stack in RAMLS0-7, a 12 KW heap in RAMGS0-1, and `.bss`/`.data` in the high RAMGS2-3 / RAMLS8-9 blocks. +- ML-DSA-87 verify uses `WOLFSSL_MLDSA_VERIFY_NO_MALLOC` + `WOLFSSL_MLDSA_VERIFY_SMALL_MEM`: ~7 KW of buffers pinned in the key struct, **zero heap**. Measure the stack high-water on hardware (sentinel fill) to record the real footprint. + +## RNG caveat + +The F28P55x has **no hardware TRNG**. `my_rng_seed_gen()` in `wolf_main.c` is a **development-only** counter seed so the benchmark's RNG-gated cases link and run -- it is **not** cryptographically secure. ML-DSA verify and the hash tests are deterministic and consume no RNG output. For a no-RNG build you can instead define `WC_NO_RNG` (the ML-DSA verify *test* still runs; the verify *benchmark* is then skipped). + +## Known iteration points + +- `NO_HMAC` / `NO_ASN`: relax if the test/benchmark harness references them unconditionally in this scoped path. +- If the link reports unresolved `XMALLOC` from a non-gated test path, raise the heap size or switch to a static-memory pool. +- `WC_16BIT_CPU`: off by default (ML-DSA/SHA use explicit `word32`/`word64`); enable only if int-width build errors appear. diff --git a/embedded/ti-c2000-f28p55x/Source/ecc_p256_kat.h b/embedded/ti-c2000-f28p55x/Source/ecc_p256_kat.h new file mode 100644 index 000000000..24cbdcfb4 --- /dev/null +++ b/embedded/ti-c2000-f28p55x/Source/ecc_p256_kat.h @@ -0,0 +1,39 @@ +/* ecc_p256_kat.h - deterministic ECDSA P-256 (SECP256R1) known-answer vector. + * + * Source: RFC 6979 Appendix A.2.5 (P-256), message "sample", hash SHA-256. + * Used for an RNG-free verify KAT on the TI C2000 C28x bring-up. + * + * Brace-init byte arrays (NOT "\x.." string literals): on cl2000 a char[]/byte[] + * initialized from a "\x.." string sign-extends bytes >= 0x80 into the 16-bit + * cell; a brace-init list stores clean octets. + */ +#ifndef ECC_P256_KAT_H +#define ECC_P256_KAT_H + +/* Public key Q = (Ux, Uy), 32 bytes each, big-endian. */ +static const unsigned char kat_p256_qx[32] = { + 0x60,0xFE,0xD4,0xBA,0x25,0x5A,0x9D,0x31,0xC9,0x61,0xEB,0x74,0xC6,0x35,0x6D,0x68, + 0xC0,0x49,0xB8,0x92,0x3B,0x61,0xFA,0x6C,0xE6,0x69,0x62,0x2E,0x60,0xF2,0x9F,0xB6 +}; +static const unsigned char kat_p256_qy[32] = { + 0x79,0x03,0xFE,0x10,0x08,0xB8,0xBC,0x99,0xA4,0x1A,0xE9,0xE9,0x56,0x28,0xBC,0x64, + 0xF2,0xF1,0xB2,0x0C,0x2D,0x7E,0x9F,0x51,0x77,0xA3,0xC2,0x94,0xD4,0x46,0x22,0x99 +}; + +/* SHA-256("sample") - the message digest that was signed. */ +static const unsigned char kat_p256_hash[32] = { + 0xAF,0x2B,0xDB,0xE1,0xAA,0x9B,0x6E,0xC1,0xE2,0xAD,0xE1,0xD6,0x94,0xF4,0x1F,0xC7, + 0x1A,0x83,0x1D,0x02,0x68,0xE9,0x89,0x15,0x62,0x11,0x3D,0x8A,0x62,0xAD,0xD1,0xBF +}; + +/* Signature (r, s), 32 bytes each, big-endian. */ +static const unsigned char kat_p256_r[32] = { + 0xEF,0xD4,0x8B,0x2A,0xAC,0xB6,0xA8,0xFD,0x11,0x40,0xDD,0x9C,0xD4,0x5E,0x81,0xD6, + 0x9D,0x2C,0x87,0x7B,0x56,0xAA,0xF9,0x91,0xC3,0x4D,0x0E,0xA8,0x4E,0xAF,0x37,0x16 +}; +static const unsigned char kat_p256_s[32] = { + 0xF7,0xCB,0x1C,0x94,0x2D,0x65,0x7C,0x41,0xD4,0x36,0xC7,0xA1,0xB6,0xE2,0x9F,0x65, + 0xF3,0xE9,0x00,0xDB,0xB9,0xAF,0xF4,0x06,0x4D,0xC4,0xAB,0x2F,0x84,0x3A,0xCD,0xA8 +}; + +#endif /* ECC_P256_KAT_H */ diff --git a/embedded/ti-c2000-f28p55x/Source/mldsa87_kat.h b/embedded/ti-c2000-f28p55x/Source/mldsa87_kat.h new file mode 100644 index 000000000..fa03dc6c1 --- /dev/null +++ b/embedded/ti-c2000-f28p55x/Source/mldsa87_kat.h @@ -0,0 +1,611 @@ +/* Auto-extracted ML-DSA-87 verify KAT vectors from wolfcrypt/test/test.c + * (ml_dsa_87_pub_key + ml_dsa_87_sig). For on-target verify validation. */ +#ifndef MLDSA87_KAT_H +#define MLDSA87_KAT_H +static const unsigned char kat_mldsa87_pub[] = { + 0x8a, 0x66, 0xe3, 0x6e, 0x3c, 0x11, 0x70, 0x9f, 0x82, 0xdd, 0xeb, 0x9e, + 0xc0, 0xd7, 0x25, 0x87, 0x0c, 0x65, 0x07, 0x9d, 0x47, 0x39, 0x5d, 0x04, + 0x42, 0x5c, 0xd6, 0x0a, 0xdc, 0x39, 0x44, 0x04, 0xd9, 0x79, 0x43, 0x87, + 0x98, 0x64, 0x88, 0x82, 0x3a, 0x31, 0xbd, 0xec, 0x66, 0xcb, 0x01, 0x90, + 0xf9, 0x85, 0xcc, 0xde, 0x54, 0x69, 0x7d, 0x84, 0xb3, 0x84, 0x3c, 0x42, + 0x0d, 0x09, 0x63, 0xdb, 0xe6, 0x5d, 0xc2, 0x8a, 0xcf, 0xe1, 0xf4, 0x86, + 0x13, 0x05, 0x09, 0x9a, 0x4d, 0x05, 0xd4, 0x31, 0xe7, 0x27, 0x39, 0xfd, + 0x3a, 0xdb, 0x63, 0x9f, 0x1c, 0x67, 0x0b, 0x01, 0xec, 0xf9, 0xff, 0xf3, + 0xda, 0xa9, 0xf4, 0x9a, 0x59, 0x52, 0x76, 0xc2, 0xd2, 0xd5, 0xdd, 0x8d, + 0xb1, 0xa2, 0xef, 0xb3, 0x73, 0x99, 0xe3, 0xcd, 0x1c, 0xf5, 0xca, 0x6e, + 0x39, 0xfa, 0x26, 0x83, 0x45, 0xe7, 0xd0, 0x9c, 0x1b, 0xf7, 0xb2, 0x64, + 0xf1, 0x70, 0x00, 0x10, 0xc0, 0x7c, 0x7f, 0xb2, 0x32, 0xce, 0x6d, 0x71, + 0xa5, 0x43, 0x7c, 0x40, 0x71, 0x09, 0x54, 0x74, 0xac, 0xb5, 0xeb, 0xe0, + 0x04, 0x02, 0xe5, 0x82, 0x4d, 0x5a, 0x85, 0x1e, 0x19, 0x86, 0x39, 0x33, + 0x92, 0x2f, 0xa9, 0xa8, 0x10, 0xd2, 0x31, 0x60, 0x16, 0x08, 0x99, 0xe3, + 0x2c, 0x93, 0x13, 0xc4, 0x4b, 0x10, 0xe0, 0x42, 0xca, 0x3f, 0x32, 0xa7, + 0xa4, 0xd2, 0xfc, 0x9c, 0x93, 0xb6, 0x5f, 0xe2, 0x5b, 0x6e, 0x40, 0x0c, + 0x63, 0xf8, 0xf8, 0xe1, 0x2d, 0xcd, 0x86, 0x07, 0x79, 0xdb, 0x61, 0xad, + 0x24, 0xfd, 0x1e, 0x66, 0x3e, 0x8d, 0x76, 0xba, 0x98, 0x8e, 0x94, 0xc7, + 0x57, 0xb1, 0x65, 0xce, 0x4f, 0x97, 0xfa, 0x34, 0x7c, 0x97, 0x6b, 0xcd, + 0x3c, 0x42, 0x81, 0xa4, 0xd1, 0x75, 0xeb, 0x6d, 0x0c, 0x31, 0x0e, 0x6f, + 0xd5, 0x75, 0xe7, 0xff, 0x83, 0xdd, 0x7a, 0x4d, 0x83, 0x67, 0xa7, 0x4b, + 0xc1, 0x74, 0xad, 0x37, 0x38, 0x99, 0xe0, 0xf5, 0x5a, 0x44, 0x36, 0xa2, + 0x20, 0x2b, 0xfc, 0xc9, 0xfa, 0x68, 0xcb, 0xf0, 0x6f, 0x0a, 0x46, 0x1d, + 0xb5, 0xca, 0x5b, 0x96, 0x1b, 0x3a, 0xaf, 0x7d, 0x01, 0x7a, 0xd2, 0x09, + 0xcc, 0xd4, 0xe4, 0xb1, 0x49, 0x34, 0x56, 0x68, 0x9c, 0x0f, 0x23, 0xe9, + 0xb3, 0x4b, 0xed, 0x3d, 0xe7, 0x8d, 0x19, 0x6e, 0xe6, 0xfa, 0x06, 0x55, + 0xb8, 0x06, 0x4d, 0xa8, 0x45, 0x20, 0x91, 0xf7, 0xfa, 0x0b, 0x6b, 0xce, + 0x55, 0xa7, 0x14, 0x1b, 0xf9, 0xea, 0xc5, 0x79, 0x78, 0xf7, 0x3a, 0xd9, + 0xfc, 0x07, 0x43, 0x06, 0x90, 0x94, 0x5e, 0xc9, 0x48, 0x51, 0xe5, 0x96, + 0x68, 0x78, 0xc8, 0xcb, 0xd1, 0xf3, 0x65, 0xef, 0x14, 0x91, 0xa3, 0xca, + 0x8b, 0x77, 0x40, 0x84, 0xf4, 0x2e, 0xe7, 0x56, 0xe3, 0xab, 0xa0, 0xa8, + 0x61, 0x93, 0x17, 0x95, 0x9e, 0xff, 0x3a, 0xd4, 0x12, 0xea, 0x13, 0xe6, + 0x82, 0x16, 0xed, 0x14, 0x70, 0x91, 0xcc, 0x72, 0x58, 0x99, 0xa1, 0x7f, + 0xf3, 0x84, 0x10, 0xf4, 0x01, 0x0d, 0x05, 0x45, 0x4d, 0xca, 0x05, 0x03, + 0x75, 0x7e, 0xbb, 0x44, 0x2e, 0xf5, 0xee, 0xed, 0x64, 0x9b, 0xd3, 0xde, + 0x3e, 0xfc, 0x31, 0x8c, 0xca, 0x23, 0x66, 0x25, 0xac, 0x5f, 0x0f, 0x33, + 0x0f, 0xd2, 0xe9, 0xc9, 0x96, 0x2a, 0xe2, 0xb8, 0xed, 0x93, 0xd3, 0x78, + 0xd8, 0x81, 0xe4, 0x52, 0x9a, 0xc6, 0x64, 0x1d, 0x2d, 0x5f, 0x93, 0x9a, + 0x2e, 0x73, 0xc4, 0x17, 0xae, 0xc6, 0x08, 0x0d, 0x2d, 0xe9, 0x4b, 0x10, + 0x29, 0xa8, 0x4e, 0x8c, 0x08, 0x59, 0x87, 0x10, 0x0d, 0x5d, 0xfa, 0xec, + 0xd6, 0x42, 0xf6, 0x5c, 0xa4, 0x0d, 0xaa, 0x64, 0x8e, 0x20, 0xa5, 0x50, + 0x9f, 0x0b, 0x85, 0x37, 0x57, 0x15, 0x7c, 0xb1, 0xe4, 0xdd, 0xd5, 0x19, + 0x3b, 0x10, 0x7d, 0x22, 0xdb, 0x53, 0x8b, 0x7b, 0x32, 0xf7, 0xf2, 0x24, + 0x92, 0xb2, 0x05, 0xd1, 0xfd, 0xfc, 0x11, 0xd6, 0xfd, 0x3c, 0x8d, 0xd7, + 0xb0, 0x58, 0x50, 0x06, 0x84, 0x61, 0xa6, 0x78, 0x04, 0x1d, 0x7f, 0x92, + 0x0e, 0x8b, 0xb3, 0x63, 0x43, 0xc5, 0x30, 0x4c, 0xce, 0x2b, 0x44, 0x70, + 0x53, 0x7c, 0xb5, 0xbd, 0x30, 0xcb, 0x41, 0x19, 0x27, 0x69, 0xfe, 0x41, + 0x92, 0xae, 0xf0, 0x37, 0x33, 0xf0, 0x95, 0xe4, 0xe8, 0x4f, 0x75, 0x41, + 0x64, 0x87, 0xc5, 0x68, 0xd3, 0xce, 0xfa, 0xaa, 0xe8, 0x59, 0x88, 0xfe, + 0x24, 0x46, 0x27, 0x60, 0x71, 0x36, 0x78, 0x66, 0x3c, 0x36, 0x8e, 0xdb, + 0x90, 0x67, 0xa5, 0x6a, 0xfe, 0xd3, 0x23, 0x28, 0x91, 0x34, 0x24, 0x67, + 0x4b, 0x01, 0x6a, 0x0e, 0x02, 0xb7, 0xf0, 0xa8, 0xd4, 0x76, 0xd5, 0xa8, + 0x1c, 0xd3, 0xb3, 0x7d, 0x74, 0xc6, 0x17, 0x96, 0xa7, 0xf9, 0xad, 0x24, + 0x36, 0xd2, 0xeb, 0x34, 0x5a, 0xcc, 0x9c, 0x01, 0x99, 0xbe, 0x21, 0x4f, + 0x27, 0x9d, 0x6b, 0xca, 0x27, 0x1b, 0x60, 0x51, 0x41, 0x23, 0xe1, 0xcb, + 0xfc, 0x17, 0x2e, 0x1a, 0x4d, 0x3d, 0x51, 0xb3, 0x91, 0x8c, 0x53, 0x4d, + 0xd7, 0xbc, 0xa4, 0x07, 0xd7, 0x17, 0x19, 0x18, 0x61, 0x38, 0x4e, 0x05, + 0x81, 0x3f, 0x43, 0x8a, 0x00, 0x60, 0xdc, 0x30, 0xf4, 0x38, 0x3f, 0x93, + 0x82, 0x10, 0x29, 0x73, 0xa9, 0xbd, 0x63, 0x15, 0x7d, 0xac, 0x2e, 0xc9, + 0x05, 0xc1, 0x01, 0x41, 0x18, 0x5a, 0xc0, 0xc8, 0xc7, 0x81, 0x69, 0xe7, + 0x24, 0x21, 0x57, 0xaf, 0x88, 0x73, 0x7c, 0x53, 0x29, 0xae, 0x5a, 0xdf, + 0x76, 0x37, 0x56, 0x4f, 0x1f, 0x6b, 0xfd, 0x71, 0xbb, 0x80, 0x4a, 0xd7, + 0x53, 0x50, 0x10, 0x2d, 0xfc, 0x1a, 0xaf, 0x7c, 0x1f, 0xe8, 0xd0, 0x6c, + 0xa6, 0x45, 0x3d, 0xb5, 0x3d, 0xb2, 0xfc, 0x97, 0xa9, 0xbf, 0x7c, 0x0f, + 0x32, 0x7a, 0xcc, 0xa9, 0x2f, 0xd0, 0xc6, 0xe6, 0xcd, 0x04, 0x1d, 0x71, + 0x91, 0xb9, 0x59, 0x4b, 0xad, 0xa0, 0xde, 0x9e, 0xdc, 0x9c, 0x10, 0xeb, + 0x8d, 0xd6, 0x65, 0x57, 0xbc, 0x96, 0xfd, 0x0f, 0xcc, 0x73, 0xbe, 0x39, + 0x27, 0x99, 0x94, 0xf5, 0xe1, 0xbb, 0x32, 0xcd, 0x27, 0x7e, 0x08, 0xa0, + 0xd2, 0x92, 0x39, 0xeb, 0x71, 0xc8, 0xe8, 0x34, 0x57, 0x34, 0x4b, 0x20, + 0x3f, 0xe2, 0x68, 0xec, 0xc0, 0x8a, 0x71, 0xa3, 0x16, 0xa2, 0x91, 0x77, + 0xde, 0x41, 0x12, 0xa5, 0xf5, 0x2a, 0x63, 0x60, 0x55, 0xd0, 0x33, 0xa4, + 0xa7, 0x2e, 0xcb, 0x80, 0x08, 0xe5, 0x76, 0x16, 0x75, 0x04, 0x57, 0xe3, + 0x14, 0x71, 0x4e, 0x57, 0x29, 0x23, 0x0e, 0xc0, 0xcc, 0xad, 0xba, 0xdc, + 0x96, 0x5d, 0x23, 0x49, 0x42, 0xd8, 0x91, 0x08, 0x0d, 0x52, 0xf4, 0x5f, + 0xcd, 0xb7, 0x03, 0xaa, 0x73, 0x26, 0xa8, 0xd5, 0x5b, 0x0c, 0x85, 0xc8, + 0x84, 0x50, 0x9e, 0x70, 0x18, 0x45, 0x27, 0x82, 0x20, 0x75, 0xad, 0x52, + 0x5c, 0x80, 0x4b, 0xb1, 0x0b, 0x3b, 0x30, 0x39, 0x02, 0x54, 0x18, 0x5d, + 0x02, 0x9e, 0x85, 0x31, 0x4a, 0x07, 0x9c, 0x59, 0x5d, 0xab, 0x13, 0x4f, + 0x8f, 0x6e, 0x39, 0x20, 0xb2, 0xc5, 0x31, 0x93, 0xc6, 0xcc, 0xfb, 0xdc, + 0x15, 0xba, 0x3d, 0xcc, 0xbb, 0xd2, 0x6f, 0x04, 0x21, 0xdf, 0x0b, 0x27, + 0x5c, 0xd2, 0x6e, 0xfa, 0xda, 0x86, 0x5d, 0xe4, 0xca, 0xa4, 0x90, 0x22, + 0xa2, 0x80, 0xb5, 0x33, 0x17, 0xdb, 0x9b, 0x7b, 0x0a, 0xcc, 0x0f, 0x9b, + 0x38, 0x06, 0xdf, 0x10, 0x11, 0xa1, 0xd7, 0x2c, 0x24, 0xf0, 0xa8, 0x34, + 0x24, 0xfb, 0x99, 0xba, 0x0a, 0xb5, 0xa1, 0x94, 0x6c, 0x2d, 0xf8, 0xda, + 0x74, 0xaf, 0x19, 0x59, 0x84, 0xb2, 0x68, 0x1c, 0xef, 0xa1, 0xf5, 0x18, + 0x8f, 0x10, 0xf6, 0xb3, 0x6d, 0x33, 0x87, 0xe0, 0x25, 0xc8, 0x65, 0x5c, + 0x2f, 0x51, 0x07, 0x83, 0x69, 0x1b, 0xce, 0xa8, 0xe6, 0xe4, 0x27, 0x62, + 0x5d, 0x9b, 0x7f, 0xa7, 0x07, 0xc8, 0x54, 0x86, 0x90, 0xa5, 0x06, 0x6a, + 0x94, 0x80, 0x84, 0x97, 0xaa, 0x2a, 0xb9, 0x79, 0xe5, 0x19, 0x7a, 0x91, + 0xef, 0x8b, 0x58, 0xdc, 0xf9, 0x90, 0x94, 0xa2, 0x25, 0x4c, 0x69, 0xd8, + 0x6e, 0x9e, 0xad, 0xf8, 0x82, 0x17, 0x37, 0xc9, 0x20, 0x15, 0x24, 0x40, + 0xe5, 0xc6, 0xc1, 0xc7, 0xbd, 0xd4, 0x62, 0xff, 0x16, 0x6d, 0xa5, 0xec, + 0xe9, 0x67, 0x41, 0x9d, 0x3e, 0xfb, 0x22, 0x81, 0x80, 0x61, 0x37, 0x45, + 0xa5, 0x9f, 0x70, 0xff, 0xd4, 0x99, 0x3d, 0x79, 0x45, 0xd0, 0x27, 0xc2, + 0x32, 0xbe, 0xd4, 0xe2, 0x53, 0xa8, 0x8c, 0x94, 0x8b, 0xbe, 0x8a, 0x43, + 0xf7, 0x2a, 0x28, 0x49, 0xf4, 0xce, 0x2e, 0x0b, 0x98, 0xc7, 0xaf, 0x7d, + 0x51, 0x2e, 0xda, 0xd0, 0x7a, 0xfa, 0x91, 0x3a, 0xe6, 0xe7, 0x64, 0xd6, + 0x09, 0xd8, 0x5d, 0x6a, 0x97, 0xcf, 0x89, 0x96, 0x72, 0x21, 0x97, 0x61, + 0xc5, 0x1b, 0xd8, 0xa1, 0xf0, 0xcd, 0x9d, 0xe4, 0xe9, 0x13, 0xd0, 0x16, + 0x41, 0x20, 0xa4, 0x2c, 0x33, 0xf5, 0x3d, 0xfe, 0x80, 0xe8, 0xb2, 0x52, + 0x0e, 0x18, 0x31, 0x19, 0x50, 0xeb, 0xc6, 0x99, 0x43, 0xab, 0x9a, 0x59, + 0x5d, 0x6c, 0x84, 0x00, 0x88, 0x45, 0x7c, 0x73, 0xdf, 0x56, 0x61, 0x3a, + 0xe1, 0x55, 0xb8, 0x59, 0x13, 0xcc, 0x0e, 0x53, 0xe9, 0xf4, 0x74, 0xa0, + 0xf2, 0x15, 0xd2, 0xa8, 0xf9, 0xd4, 0x0d, 0x3d, 0xe7, 0x3d, 0x7d, 0x5b, + 0x19, 0x89, 0x8b, 0x2c, 0x4d, 0x8a, 0xeb, 0xc3, 0x43, 0x31, 0x9a, 0x45, + 0x72, 0x5b, 0x25, 0xb6, 0xa2, 0xc1, 0x98, 0xe3, 0x8a, 0xd4, 0x90, 0xd0, + 0x3e, 0x13, 0xf0, 0xd7, 0x90, 0x34, 0x94, 0xcc, 0xf1, 0x0a, 0xa9, 0x30, + 0xd1, 0x95, 0x43, 0x07, 0xcd, 0xd2, 0xca, 0xb0, 0xe5, 0xd4, 0xf1, 0xa1, + 0xc5, 0x9b, 0xf4, 0x98, 0x28, 0xba, 0xde, 0x40, 0xd6, 0x98, 0x98, 0x20, + 0x9c, 0x84, 0x9e, 0xc6, 0x57, 0xd8, 0x84, 0xc4, 0xa2, 0x9b, 0x53, 0x50, + 0xa5, 0xa6, 0x0b, 0x47, 0xe8, 0x08, 0x7d, 0xd7, 0x09, 0xa4, 0x0c, 0x2b, + 0x27, 0xde, 0xf9, 0x78, 0xbc, 0xa4, 0xb6, 0xc6, 0x1b, 0xda, 0xce, 0x6a, + 0xf8, 0x1a, 0xf5, 0xfe, 0x7b, 0xab, 0x58, 0x7c, 0xdc, 0x72, 0x02, 0x94, + 0x99, 0xf0, 0x3c, 0x37, 0x87, 0x5b, 0xd2, 0x4b, 0x5a, 0x80, 0x83, 0xd7, + 0xfc, 0x9d, 0xa7, 0x51, 0x81, 0xb8, 0x62, 0xff, 0x4b, 0xb3, 0x9f, 0x07, + 0xc3, 0x54, 0xfb, 0x41, 0x85, 0x42, 0x9d, 0xac, 0x27, 0x81, 0x2e, 0xaf, + 0x98, 0x67, 0x8c, 0x23, 0xad, 0x45, 0xfe, 0x6a, 0x57, 0x9f, 0x18, 0xc5, + 0x71, 0x8c, 0xad, 0x3f, 0x30, 0x3c, 0xaa, 0x47, 0x8d, 0xba, 0xc8, 0x7f, + 0x03, 0x1c, 0x86, 0xee, 0xba, 0x3f, 0x59, 0x45, 0xd4, 0xd0, 0xf5, 0x54, + 0x9e, 0xcb, 0x08, 0xcf, 0xca, 0x40, 0x0a, 0x06, 0xc0, 0x1e, 0x60, 0x1f, + 0x33, 0xbf, 0x2c, 0xa8, 0x5f, 0xce, 0x23, 0xa0, 0xe2, 0x1c, 0x2d, 0x56, + 0x2a, 0x44, 0x61, 0x58, 0xf1, 0x84, 0x63, 0x4f, 0x0d, 0x5e, 0xfb, 0x83, + 0x0f, 0x36, 0x1b, 0xf4, 0x8f, 0x17, 0x82, 0x2e, 0x04, 0x2c, 0x77, 0x9d, + 0x32, 0x58, 0xb8, 0xb0, 0xf9, 0x44, 0xd2, 0xf6, 0x84, 0xa4, 0x8b, 0x28, + 0x53, 0xd6, 0x99, 0x81, 0x84, 0x43, 0xf0, 0xc1, 0x15, 0xc6, 0x74, 0x4f, + 0xab, 0x05, 0xcc, 0x80, 0xdf, 0xef, 0xcf, 0xaf, 0x14, 0x82, 0xdf, 0x51, + 0x7c, 0x28, 0x5e, 0x5b, 0x27, 0x5e, 0x91, 0x8b, 0x54, 0x3d, 0x54, 0x26, + 0xb0, 0x3f, 0xd7, 0xc5, 0xce, 0xf3, 0x6d, 0x2c, 0x12, 0xc6, 0xb4, 0x48, + 0x60, 0x11, 0x9c, 0xef, 0x29, 0x98, 0x9c, 0x76, 0x4e, 0x73, 0x2b, 0xd2, + 0x23, 0x53, 0x7d, 0x03, 0xc2, 0x2f, 0x8a, 0xa1, 0xe2, 0x84, 0x54, 0x2d, + 0xd8, 0xc6, 0x55, 0x77, 0x9d, 0x07, 0x67, 0x1f, 0x1a, 0xd3, 0x57, 0x4c, + 0x25, 0x79, 0x8f, 0xd8, 0x82, 0xc2, 0x4d, 0x87, 0x84, 0x33, 0xdc, 0x47, + 0xed, 0x9e, 0xfb, 0xd2, 0x62, 0xc8, 0x50, 0x76, 0xda, 0x3c, 0x3c, 0x05, + 0x0e, 0x2d, 0x30, 0x56, 0xca, 0x4d, 0x6a, 0xe2, 0x17, 0x24, 0x26, 0x9c, + 0xff, 0x09, 0xec, 0xb3, 0x94, 0xec, 0xab, 0x69, 0xb2, 0xf0, 0xa5, 0x66, + 0x18, 0x92, 0x49, 0x6b, 0x90, 0xf5, 0x77, 0x5a, 0x18, 0xe5, 0x51, 0x36, + 0x4a, 0x35, 0x54, 0x98, 0x48, 0x04, 0xa9, 0x0f, 0xcb, 0x55, 0xf1, 0x71, + 0xad, 0x1a, 0x4a, 0x2c, 0x0e, 0x5d, 0x5e, 0x77, 0x47, 0xf5, 0x46, 0x17, + 0x6b, 0x94, 0x2a, 0xbc, 0x40, 0xe5, 0xa7, 0xa6, 0x88, 0x41, 0x76, 0x22, + 0x47, 0xd1, 0xe8, 0x2b, 0x18, 0x48, 0x21, 0xc0, 0xe8, 0x4f, 0xe2, 0xb2, + 0x7e, 0x03, 0xbb, 0x25, 0x9c, 0xc8, 0x68, 0x66, 0x48, 0x25, 0x6a, 0xf2, + 0x64, 0x29, 0xec, 0x79, 0xba, 0xdb, 0x34, 0xe1, 0xd4, 0xf9, 0x52, 0x0e, + 0xfd, 0x8d, 0x86, 0x94, 0x71, 0xd8, 0xe0, 0x86, 0x02, 0x9b, 0xd4, 0x65, + 0x69, 0x5e, 0x01, 0x32, 0x87, 0x59, 0xd8, 0x6c, 0xbc, 0x8a, 0x9f, 0x58, + 0x28, 0x8c, 0x97, 0xef, 0x33, 0xb2, 0xda, 0x45, 0xa0, 0xec, 0xe5, 0x5b, + 0xac, 0xc6, 0x65, 0xc1, 0xb6, 0xcb, 0xf7, 0x85, 0x0e, 0xfa, 0x78, 0x36, + 0x30, 0x84, 0x90, 0xa8, 0xf8, 0x42, 0x25, 0xa5, 0xdd, 0xdc, 0xdc, 0x89, + 0xd3, 0xf0, 0x73, 0x9a, 0xd8, 0x95, 0x8f, 0x04, 0xbf, 0xc1, 0xfd, 0x94, + 0xff, 0xe6, 0xf8, 0x4e, 0xc6, 0x43, 0xc9, 0x60, 0x30, 0xe9, 0x68, 0xa8, + 0x76, 0xfb, 0xfa, 0xdf, 0xc0, 0x9b, 0xbc, 0xbc, 0x34, 0xe4, 0x38, 0xfd, + 0x93, 0xb0, 0x47, 0xb2, 0x3e, 0x83, 0x6c, 0xef, 0xe1, 0xaf, 0x35, 0xb4, + 0x90, 0x2a, 0x32, 0xaf, 0x25, 0x3f, 0x3e, 0x72, 0x61, 0xc0, 0x0f, 0x29, + 0xbb, 0x46, 0x6e, 0x2e, 0x94, 0x7d, 0xdd, 0xb7, 0x67, 0x1f, 0x7b, 0x64, + 0xcb, 0xa5, 0x9a, 0x58, 0x63, 0x20, 0xa7, 0xc0, 0x94, 0xa9, 0xad, 0x90, + 0x7d, 0xf3, 0x2b, 0x61, 0x2b, 0x64, 0x3d, 0x8a, 0xc3, 0xd1, 0xcb, 0xad, + 0x36, 0x44, 0xe6, 0x29, 0x8b, 0x3d, 0x95, 0x7c, 0xa7, 0xa2, 0xfa, 0x1b, + 0x16, 0x8d, 0x9e, 0xc4, 0xf8, 0x4c, 0x76, 0x20, 0x00, 0x68, 0x07, 0x99, + 0x9c, 0x60, 0xe6, 0x16, 0x6a, 0x6f, 0x8a, 0xbe, 0x71, 0x95, 0xa1, 0xcb, + 0xfe, 0x7c, 0x41, 0x59, 0x61, 0x20, 0xf9, 0x54, 0x3c, 0xb1, 0x19, 0x5c, + 0x42, 0x67, 0x3f, 0xff, 0xf3, 0x32, 0x21, 0x9c, 0x9e, 0x88, 0xf9, 0x97, + 0x00, 0x43, 0x73, 0x4a, 0xfc, 0x54, 0xeb, 0x27, 0x79, 0x14, 0x85, 0xd3, + 0xdc, 0x47, 0xb3, 0x6d, 0x24, 0xd3, 0xf7, 0x7a, 0xfb, 0x90, 0x7c, 0x6e, + 0xcd, 0x4e, 0xbf, 0x26, 0x76, 0xd2, 0xe8, 0xcc, 0x67, 0xd1, 0x23, 0x3c, + 0x94, 0x16, 0x1e, 0x07, 0x36, 0x7c, 0x96, 0xf6, 0xe8, 0x50, 0x72, 0x26, + 0x56, 0x67, 0x89, 0xa9, 0x11, 0xfb, 0x1d, 0xb8, 0xb9, 0x2a, 0x55, 0xb7, + 0x85, 0xf7, 0x40, 0xa2, 0xfc, 0x9f, 0x30, 0xec, 0x8f, 0x9a, 0x1c, 0xc8, + 0xe4, 0xc5, 0x1f, 0xcb, 0x0a, 0x60, 0x80, 0x41, 0xec, 0x88, 0x8a, 0xda, + 0x7c, 0x7a, 0xa1, 0x96, 0x51, 0x62, 0x16, 0x63, 0x75, 0x36, 0x28, 0x7c, + 0xc9, 0xd0, 0x27, 0x0c, 0x9e, 0x18, 0x4a, 0x82, 0xf7, 0x02, 0xb9, 0x40, + 0x8f, 0xd5, 0x97, 0x7a, 0x35, 0xa9, 0x3a, 0xb3, 0x8b, 0x6b, 0xf1, 0x9a, + 0xd1, 0xe7, 0x14, 0x38, 0x5e, 0xba, 0x8c, 0xbf, 0x32, 0xaa, 0x34, 0x30, + 0x7c, 0x1e, 0x11, 0xcd, 0x1f, 0x9f, 0xcf, 0x4d, 0x14, 0xce, 0x67, 0xf9, + 0x9c, 0x89, 0x07, 0x92, 0x44, 0x6e, 0x9a, 0x16, 0xe4, 0xfb, 0x67, 0x01, + 0x3f, 0x4c, 0x14, 0x89, 0x33, 0x87, 0x46, 0xc6, 0xe4, 0x66, 0x94, 0xd4, + 0x87, 0x4f, 0x2c, 0x92, 0x1b, 0xae, 0x82, 0xe7, 0x99, 0xaa, 0xb4, 0x99, + 0x81, 0x26, 0xa6, 0x6f, 0x1d, 0xc1, 0x95, 0x80, 0xe9, 0xea, 0xe3, 0x44, + 0x6a, 0x2b, 0xd2, 0xe0, 0x0d, 0x69, 0x42, 0xf7, 0x27, 0x6b, 0x4f, 0x02, + 0x7a, 0x33, 0x7b, 0x43, 0x3d, 0xef, 0x10, 0xaa, 0xab, 0xc5, 0xa2, 0xf0, + 0xbb, 0x07, 0x4b, 0x26, 0x0c, 0x58, 0xcd, 0x3b, 0xd2, 0x6d, 0xa5, 0x32, + 0x37, 0x88, 0x4e, 0x8b, 0xe3, 0x75, 0xb0, 0xbb, 0x87, 0xea, 0xa4, 0x53, + 0xf3, 0xff, 0x39, 0x92, 0x44, 0xab, 0x7b, 0x71, 0x62, 0x31, 0x6b, 0x31, + 0xca, 0x97, 0xba, 0xd7, 0x41, 0xe0, 0x47, 0x47, 0x4f, 0x77, 0xa2, 0x35, + 0x62, 0x7a, 0xc1, 0xb6, 0x69, 0x10, 0x09, 0xce, 0xfc, 0x92, 0xcc, 0xc5, + 0x7a, 0x11, 0xf1, 0xc1, 0xa0, 0x80, 0xe5, 0x42, 0x17, 0xb6, 0x3f, 0xab, + 0xc1, 0xa2, 0x41, 0xfb, 0xe3, 0x98, 0x2d, 0x7a, 0xe4, 0x1b, 0x1f, 0x7e, + 0x71, 0x3c, 0x3e, 0x90, 0x8c, 0x60, 0x30, 0xb7, 0x73, 0x06, 0x1f, 0x8a, + 0xce, 0x50, 0x20, 0x7c, 0xfa, 0x8c, 0xf2, 0x14, 0xd9, 0x00, 0xa2, 0x21, + 0xea, 0x10, 0x36, 0x21, 0x6f, 0x7f, 0x13, 0xe3, 0x6c, 0xb2, 0xd6, 0xa5, + 0xa6, 0x6e, 0xa9, 0xe7, 0x1d, 0xdf, 0xc9, 0x97, 0x60, 0x75, 0xa3, 0x55, + 0xa1, 0x2c, 0x94, 0xd7, 0x85, 0x4b, 0x44, 0xc6, 0x9c, 0x17, 0xc2, 0xad, + 0xe6, 0x56, 0x72, 0x1d, 0xb9, 0x13, 0x54, 0xfe, 0x8c, 0xec, 0xf4, 0xa3, + 0x54, 0x6b, 0x31, 0xbc, 0x55, 0x9e, 0x01, 0xd4, 0x9b, 0x24, 0x9e, 0x51, + 0xaf, 0x67, 0x76, 0x02, 0xf7, 0x34, 0x6a, 0xaa, 0xb0, 0x3c, 0x70, 0x2e, + 0xc8, 0x86, 0xfa, 0x40, 0x89, 0x12, 0xb7, 0x49, 0x38, 0x0b, 0xf7, 0x66, + 0xd2, 0x2e, 0x58, 0xf1, 0x22, 0x3b, 0xb3, 0x40, 0x6b, 0x7a, 0x68, 0x4d, + 0x42, 0xfd, 0xbf, 0xa0, 0xf7, 0x2f, 0x63, 0x4a, 0x87, 0xe7, 0x99, 0x52, + 0x6e, 0xe7, 0xdd, 0xca, 0x19, 0x71, 0xee, 0x92, 0xe2, 0x68, 0x0e, 0xe1, + 0xb7, 0x90, 0x1f, 0xc4, 0xef, 0xf8, 0xf6, 0x85, 0x53, 0x18, 0x33, 0x86, + 0x15, 0xc8, 0x29, 0x58, 0x6f, 0xf0, 0x1c, 0x14, 0x73, 0xa9, 0x8e, 0x88, + 0x74, 0xd4, 0x21, 0xf5, 0xc6, 0x7c, 0xd8, 0x96, 0x0f, 0xb0, 0xa6, 0x7b, + 0xf7, 0x72, 0x15, 0xd7, 0x30, 0x6b, 0x15, 0x1d, 0x3f, 0xb7, 0x4e, 0xaa, + 0xc0, 0x52, 0x1d, 0x84, 0xbf, 0x98, 0xbd, 0x33, 0x02, 0xab, 0x8b, 0xd0, + 0x9c, 0x85, 0x2f, 0xa3, 0xfb, 0x46, 0x8d, 0x4d, 0x97, 0x1a, 0x8a, 0x3c, + 0x73, 0x5b, 0x3b, 0x58, 0x26, 0xba, 0x6b, 0x45, 0x2e, 0x24, 0x66, 0x79, + 0x7d, 0xc4, 0xf8, 0x8c, 0x05, 0x7d, 0x5c, 0x23, 0xb9, 0xe8, 0x5d, 0xfe, + 0xc9, 0x84, 0xe5, 0x58, 0x40, 0xa4, 0xb7, 0x55, 0x74, 0x69, 0x92, 0x9c, + 0x3e, 0x19, 0xb1, 0xb6, 0x51, 0xe9, 0x71, 0xcc, 0x96, 0x2b, 0x01, 0x71, + 0xf5, 0xb9, 0xde, 0x77, 0xfe, 0x2e, 0x74, 0x9c, 0x6a, 0x52, 0x17, 0x1e, + 0xea, 0xd9, 0xc8, 0x14, 0xbe, 0x61, 0xdf, 0xe9, 0x96, 0x24, 0x5a, 0x9a, + 0xd8, 0xd7, 0xad, 0x71, 0xe0, 0xf4, 0xbb, 0x9e, 0xae, 0x95, 0xcd, 0x58, + 0x94, 0x81, 0xee, 0x46, 0x84, 0x65, 0x39, 0xb1, 0x1b, 0x1e, 0xf5, 0x50, + 0xad, 0x56, 0x58, 0xb7, 0x53, 0x9b, 0x2a, 0x2f, 0x09, 0x61, 0x57, 0xda, + 0xf5, 0xdc, 0x9f, 0x3c, 0x6c, 0x69, 0x0d, 0x61, 0x49, 0xb2, 0xe0, 0xb2, + 0xe5, 0xef, 0x19, 0xbe, 0x04, 0xf6, 0x6b, 0xad, 0x41, 0x4c, 0x5a, 0x50, + 0xf6, 0xac, 0x1b, 0x25, 0x8a, 0xdd, 0xe3, 0x57, 0xab, 0x7c, 0x92, 0xe4 +}; +static const unsigned char kat_mldsa87_sig[] = { + 0x20, 0xff, 0x12, 0xe1, 0x87, 0xf6, 0x11, 0x38, 0xff, 0x41, 0xd0, 0x8f, + 0xcd, 0x7e, 0xd1, 0xf6, 0x21, 0x17, 0xd0, 0x46, 0xe9, 0x86, 0x83, 0x1b, + 0xaf, 0xe5, 0x2b, 0x59, 0x21, 0xd1, 0x6b, 0xc9, 0xdb, 0x34, 0xdc, 0xba, + 0xfd, 0xd3, 0xf8, 0x71, 0x49, 0xd8, 0x31, 0xbc, 0x48, 0x83, 0x22, 0x7b, + 0xfd, 0x6a, 0x93, 0xa6, 0x39, 0x4c, 0xda, 0xdb, 0x15, 0xe7, 0x41, 0x14, + 0xb4, 0xb8, 0xfe, 0xb0, 0x1f, 0xf9, 0x0a, 0x2c, 0x0b, 0xc0, 0xac, 0x09, + 0x84, 0x69, 0x5e, 0x64, 0x8c, 0xa8, 0xee, 0xa1, 0x52, 0x22, 0xde, 0x0d, + 0xc7, 0x25, 0xef, 0xa8, 0xfd, 0x8c, 0xb9, 0x45, 0x4f, 0xa4, 0x9c, 0xbc, + 0x70, 0xf2, 0x88, 0xea, 0x79, 0x13, 0xb0, 0xfc, 0xe6, 0x41, 0x48, 0x1c, + 0x33, 0x48, 0xa2, 0x77, 0x75, 0x37, 0x9f, 0xc1, 0x86, 0x94, 0xcd, 0x69, + 0x98, 0x87, 0x47, 0x49, 0x75, 0x93, 0xf1, 0xa4, 0x2d, 0x8e, 0xa8, 0x7e, + 0x0f, 0x95, 0xf5, 0x3e, 0x5d, 0x31, 0x2d, 0xc9, 0x58, 0x1c, 0x42, 0xfd, + 0x79, 0x6a, 0x49, 0xa3, 0x84, 0xc5, 0x2e, 0x8d, 0x96, 0x9c, 0xc8, 0x05, + 0x93, 0xdb, 0x6d, 0xbf, 0x83, 0x34, 0xc2, 0x81, 0x47, 0x90, 0xc9, 0xa9, + 0x82, 0xbd, 0xe1, 0xc8, 0x89, 0xa2, 0x36, 0x47, 0xed, 0xfb, 0x47, 0x57, + 0x01, 0x1a, 0x75, 0x8c, 0x6b, 0x83, 0xcf, 0x56, 0xae, 0x52, 0x66, 0x8b, + 0xab, 0x7f, 0x0c, 0xec, 0xde, 0x5c, 0x13, 0xbe, 0xbd, 0x5b, 0x74, 0x28, + 0xb5, 0xd7, 0x68, 0xd5, 0xd2, 0xe9, 0x96, 0x3b, 0x55, 0xda, 0x3a, 0x93, + 0x3c, 0xd9, 0x9f, 0x53, 0x2a, 0x31, 0x84, 0x45, 0x3f, 0xee, 0x2b, 0xfc, + 0x92, 0xb0, 0x9c, 0xc6, 0x16, 0x16, 0x4f, 0x33, 0x41, 0x17, 0x58, 0xbe, + 0x5d, 0x57, 0x4b, 0x04, 0x82, 0xe3, 0xb3, 0x68, 0xdf, 0x7c, 0x93, 0xce, + 0x9d, 0xf6, 0x7e, 0x21, 0x3d, 0x28, 0x1c, 0xf0, 0x37, 0x46, 0xf2, 0xc2, + 0x73, 0x7c, 0xbe, 0x98, 0x0e, 0x09, 0x75, 0xa7, 0x21, 0x11, 0xa9, 0xd6, + 0xd1, 0x47, 0xac, 0xd0, 0x19, 0x48, 0x3b, 0x74, 0xc1, 0x3c, 0x37, 0x43, + 0x49, 0x12, 0x62, 0xee, 0xaf, 0x5c, 0x38, 0xf7, 0x8a, 0xce, 0xb3, 0x7a, + 0x05, 0x16, 0xd4, 0x71, 0x8b, 0xbe, 0x1a, 0xe0, 0x1e, 0xbc, 0x4b, 0x54, + 0x0f, 0xb5, 0x73, 0x2b, 0xb8, 0x3a, 0x75, 0xf0, 0x26, 0xcd, 0xf9, 0xca, + 0x32, 0xf9, 0x7e, 0x15, 0x38, 0x75, 0x9c, 0x4d, 0xbc, 0x11, 0xf8, 0xea, + 0x8e, 0xe8, 0x38, 0x17, 0xc5, 0x62, 0xf4, 0x34, 0xfb, 0xd6, 0xf5, 0x76, + 0xfc, 0xa3, 0xf3, 0x44, 0xf9, 0xab, 0x2e, 0x9a, 0x68, 0xcd, 0xa1, 0x29, + 0xff, 0xda, 0xe8, 0xb5, 0xb0, 0x20, 0x5d, 0x02, 0x01, 0x62, 0x26, 0x44, + 0x32, 0xc8, 0x94, 0xf8, 0xf1, 0xaa, 0xf9, 0xc2, 0x86, 0xcb, 0x55, 0x7f, + 0x8d, 0xb3, 0xf6, 0x63, 0xb1, 0xa4, 0x95, 0x57, 0xb8, 0x1d, 0xc3, 0x42, + 0xd2, 0x4b, 0x69, 0xcd, 0x7a, 0x10, 0x5b, 0x6a, 0x13, 0xd1, 0x02, 0x98, + 0x38, 0x87, 0x9b, 0x9a, 0x5a, 0x66, 0x73, 0xcb, 0x75, 0xd0, 0x7a, 0x4b, + 0xad, 0x23, 0x06, 0x1c, 0xc8, 0x6b, 0x0c, 0xa8, 0xfe, 0x7b, 0x8f, 0x65, + 0x50, 0xd7, 0xf7, 0x76, 0x88, 0x42, 0xe0, 0x5e, 0x18, 0x91, 0x8b, 0x99, + 0x37, 0x56, 0x08, 0x91, 0xe7, 0x01, 0xe7, 0x05, 0xd5, 0xed, 0x43, 0x25, + 0x71, 0x7e, 0x3e, 0xfc, 0xc4, 0xfd, 0xed, 0x8b, 0x85, 0x16, 0x8c, 0xe3, + 0x05, 0xee, 0x51, 0x02, 0xa4, 0x4b, 0xd8, 0x3c, 0xcf, 0x4d, 0x2f, 0x2d, + 0x68, 0x6e, 0xc1, 0xd5, 0xfa, 0x91, 0xfd, 0x6a, 0xe0, 0x64, 0x85, 0x35, + 0x9c, 0x75, 0xe6, 0x0d, 0xb8, 0xec, 0x97, 0x88, 0x62, 0x98, 0x78, 0x75, + 0xc7, 0x1e, 0x68, 0xa7, 0xb9, 0x7b, 0xab, 0x75, 0x7a, 0x72, 0x3c, 0x7b, + 0xab, 0x60, 0x03, 0xb7, 0x38, 0x13, 0xe4, 0x96, 0x6e, 0xcb, 0x95, 0xcc, + 0xdc, 0x6a, 0x47, 0x67, 0x77, 0xd7, 0x95, 0xc4, 0x87, 0x66, 0xc2, 0x7e, + 0x42, 0x90, 0x59, 0x4f, 0xd6, 0xf3, 0xf4, 0xa7, 0xd0, 0x29, 0xf9, 0x5d, + 0x4b, 0x06, 0x06, 0xf7, 0x6e, 0xb2, 0xab, 0xb0, 0x8e, 0x21, 0xa6, 0xff, + 0x5e, 0x7b, 0x47, 0xb6, 0x3a, 0xa6, 0x9e, 0x19, 0xf6, 0xdf, 0x9b, 0x3b, + 0x3d, 0x07, 0x37, 0xd1, 0x0b, 0xa8, 0xf3, 0x9c, 0x43, 0x89, 0xee, 0xba, + 0x03, 0xee, 0x38, 0x74, 0x13, 0x09, 0x8e, 0x47, 0x4e, 0xa9, 0x14, 0xf5, + 0xb0, 0x55, 0xe0, 0x03, 0xe5, 0xb9, 0x53, 0xef, 0x03, 0x15, 0x60, 0xb3, + 0x4a, 0x71, 0x31, 0x4b, 0xf1, 0xc8, 0xe4, 0x63, 0x9b, 0x8b, 0x78, 0x3c, + 0x1f, 0xac, 0x27, 0x20, 0xa8, 0x53, 0x7d, 0xdd, 0x72, 0xd3, 0x90, 0x8f, + 0x71, 0xa6, 0xa7, 0xeb, 0xb0, 0xeb, 0x42, 0x96, 0xa4, 0xc3, 0xba, 0xc6, + 0x3c, 0xe7, 0x7b, 0x15, 0x1e, 0xfa, 0x15, 0x23, 0x37, 0xf3, 0xc8, 0xb2, + 0xf9, 0x46, 0x04, 0xd1, 0x5e, 0x44, 0xd7, 0x8f, 0x70, 0xb1, 0x0a, 0xde, + 0x6a, 0xe3, 0xaf, 0x9e, 0x49, 0x55, 0x78, 0x79, 0x11, 0x22, 0x87, 0xa9, + 0x54, 0x7c, 0xb4, 0x83, 0xe1, 0x25, 0xcd, 0x89, 0xa6, 0x91, 0x21, 0x7b, + 0xbe, 0x3d, 0x2f, 0x46, 0xb5, 0x5b, 0x50, 0x1a, 0xc8, 0x8d, 0x32, 0xf3, + 0x62, 0x1f, 0x24, 0x64, 0xe8, 0xb6, 0x02, 0x4f, 0x1f, 0x52, 0x3c, 0x40, + 0xfc, 0x72, 0x38, 0xd4, 0xba, 0x40, 0x8e, 0xb7, 0xc0, 0x97, 0x06, 0x16, + 0xd5, 0xe3, 0x39, 0x45, 0xd7, 0x7c, 0x0e, 0xed, 0x6b, 0x19, 0x19, 0x0a, + 0x8e, 0xcb, 0x2b, 0xee, 0x4d, 0xa1, 0x5e, 0x84, 0x22, 0x66, 0xcd, 0x4f, + 0xb9, 0x1a, 0x25, 0x85, 0x02, 0xc0, 0x67, 0xc4, 0xd5, 0x1a, 0xcb, 0xbb, + 0xde, 0x4d, 0x3c, 0x3c, 0x62, 0x9f, 0x76, 0x8f, 0x15, 0x29, 0xa5, 0xbb, + 0x5a, 0x48, 0x38, 0x66, 0xfa, 0x56, 0x0a, 0x09, 0xbd, 0xdf, 0xdf, 0x4a, + 0xe7, 0x0e, 0xa6, 0xb1, 0xb5, 0x7c, 0xe1, 0xed, 0x8d, 0x63, 0x07, 0x42, + 0xf3, 0xf8, 0x15, 0x28, 0x7c, 0x09, 0xf5, 0x02, 0x69, 0x1b, 0x88, 0x1e, + 0x3d, 0xad, 0x5f, 0x46, 0xed, 0xab, 0x2b, 0x11, 0x96, 0x73, 0xa8, 0xe8, + 0xe6, 0x64, 0x7d, 0xae, 0x13, 0xa1, 0x7d, 0x54, 0xae, 0xc0, 0x82, 0xeb, + 0x2a, 0xd1, 0x76, 0xb7, 0x9f, 0xbd, 0x33, 0x8f, 0xe7, 0xe6, 0x79, 0x92, + 0xa6, 0xaf, 0x61, 0x91, 0x49, 0xbc, 0xd2, 0x3c, 0x6f, 0x8b, 0xbe, 0x8f, + 0x5f, 0x1f, 0x00, 0x2c, 0x2e, 0x2c, 0xa0, 0x14, 0xcf, 0x34, 0x42, 0x44, + 0x41, 0x11, 0xd7, 0x37, 0xd3, 0x99, 0x44, 0x36, 0x43, 0x03, 0xb9, 0x50, + 0x4f, 0xab, 0xfe, 0x48, 0xe2, 0x4b, 0xed, 0x51, 0x8b, 0xe0, 0x04, 0x3c, + 0x93, 0x28, 0x55, 0xc8, 0x5a, 0xb3, 0x52, 0x2c, 0x56, 0xbd, 0x43, 0xb9, + 0x4a, 0x6c, 0x4c, 0xcc, 0xda, 0xba, 0x9c, 0xe6, 0x3e, 0x50, 0x8b, 0x1a, + 0xe5, 0x83, 0xc1, 0x60, 0x55, 0xb2, 0x02, 0x16, 0x54, 0x33, 0x62, 0x69, + 0x7c, 0x7d, 0x94, 0xf2, 0xb0, 0x3a, 0x22, 0xf0, 0x21, 0x46, 0xd7, 0x94, + 0x53, 0xec, 0x63, 0x4c, 0x3e, 0xc3, 0x71, 0xd1, 0xb9, 0x2e, 0x16, 0xe8, + 0x17, 0x63, 0x7e, 0x0c, 0x83, 0x05, 0x72, 0xe6, 0x20, 0x60, 0x34, 0xae, + 0x0e, 0x54, 0xa0, 0x57, 0x75, 0x93, 0x2e, 0xb8, 0x6c, 0xec, 0xda, 0x44, + 0x1b, 0xac, 0xd6, 0x75, 0xc5, 0x79, 0x3c, 0xc2, 0xa6, 0xa2, 0x7f, 0x3a, + 0xb0, 0xec, 0xeb, 0xc1, 0xe6, 0xd6, 0xae, 0xac, 0x2e, 0x55, 0x30, 0x1c, + 0x81, 0xa4, 0x4c, 0x35, 0x0e, 0xd8, 0xa6, 0x4e, 0xea, 0x0e, 0xbf, 0x79, + 0xf7, 0xdf, 0x55, 0xfc, 0xf9, 0x24, 0xb0, 0xa6, 0xba, 0xc3, 0x72, 0x42, + 0x60, 0x06, 0x44, 0x03, 0xe3, 0x40, 0x3c, 0x2a, 0x13, 0xf7, 0xdf, 0x3d, + 0xb7, 0x0d, 0x86, 0x6c, 0xb0, 0x0f, 0x2e, 0x72, 0x91, 0x16, 0x4f, 0x5f, + 0xd0, 0x3e, 0x8c, 0x36, 0xed, 0xa8, 0x6f, 0xbc, 0x65, 0xb0, 0x65, 0x99, + 0x47, 0x50, 0xa5, 0x9c, 0xea, 0xee, 0x8a, 0x44, 0x70, 0xf5, 0x31, 0x1a, + 0xe9, 0x11, 0xc1, 0xce, 0xe0, 0x21, 0x52, 0x70, 0x89, 0xf7, 0xc3, 0x35, + 0xfa, 0x55, 0x5a, 0xc5, 0x10, 0x02, 0xc4, 0xc7, 0xf7, 0xe1, 0xaf, 0x49, + 0x48, 0x61, 0xe7, 0x0d, 0xa1, 0x2d, 0x7d, 0x03, 0x00, 0x38, 0xa7, 0xd5, + 0xd3, 0xbf, 0x95, 0x29, 0xed, 0xcc, 0x70, 0x3e, 0xbe, 0x95, 0x8a, 0xdf, + 0xaf, 0xbf, 0xec, 0xf8, 0x6a, 0x4f, 0x9e, 0x69, 0xee, 0x4e, 0x3d, 0x8b, + 0x58, 0xa0, 0x2e, 0xb5, 0x83, 0x6a, 0x0e, 0x04, 0xa4, 0xa9, 0x74, 0xcb, + 0x4f, 0xb0, 0x39, 0x37, 0x8f, 0xcf, 0xbf, 0x77, 0xe4, 0x1a, 0x74, 0xcf, + 0x0e, 0x0d, 0x2d, 0x6e, 0x1d, 0xba, 0xc1, 0xf5, 0x7c, 0x54, 0x6e, 0x92, + 0xec, 0x4b, 0x03, 0xc3, 0xa4, 0x44, 0xad, 0x3e, 0x4f, 0xa4, 0xd9, 0xe9, + 0x71, 0x3c, 0xe6, 0xb6, 0xbe, 0xe7, 0xfc, 0x72, 0x76, 0x86, 0x9a, 0x73, + 0xb1, 0xb3, 0xf3, 0x84, 0xb6, 0x2a, 0x40, 0x0b, 0x8c, 0xae, 0xb3, 0xc4, + 0xdc, 0xb5, 0x21, 0x85, 0x87, 0xdc, 0x19, 0x18, 0xd5, 0xba, 0xa4, 0x5e, + 0x88, 0x89, 0xa4, 0xf4, 0x88, 0x75, 0xc2, 0x7a, 0xb4, 0xee, 0x9d, 0x54, + 0x66, 0x97, 0x70, 0x08, 0x8f, 0x99, 0x84, 0x5d, 0x5e, 0xa7, 0x6f, 0x92, + 0xe8, 0xa3, 0x65, 0xfa, 0x0e, 0x87, 0xfb, 0x3c, 0xe9, 0x17, 0x2d, 0xc7, + 0x2d, 0x30, 0x8f, 0x41, 0x82, 0x68, 0x2b, 0xf1, 0x67, 0x8e, 0xf7, 0x05, + 0x78, 0xfa, 0xc3, 0x61, 0xba, 0x35, 0xe7, 0x2f, 0x19, 0xef, 0x71, 0x36, + 0xac, 0x5b, 0xf0, 0x45, 0x30, 0x70, 0xdc, 0xc7, 0xab, 0x7b, 0x62, 0x17, + 0x9d, 0xc4, 0x43, 0x6f, 0xfc, 0x02, 0x56, 0x5f, 0x65, 0xaa, 0x68, 0x3b, + 0x5c, 0xfa, 0x71, 0x28, 0x89, 0xe9, 0x28, 0x2f, 0x95, 0x4b, 0xfc, 0xe6, + 0xe7, 0xc8, 0x44, 0x28, 0x5c, 0x3c, 0x08, 0x5f, 0x9c, 0xbc, 0x41, 0x68, + 0x91, 0x98, 0x7a, 0x00, 0x63, 0xc9, 0x5c, 0x75, 0x8f, 0xcc, 0x33, 0x77, + 0x7b, 0xd0, 0x2d, 0xe8, 0xa2, 0x98, 0xa4, 0x1b, 0xfa, 0x09, 0x67, 0x7b, + 0x25, 0x96, 0x19, 0xf4, 0x77, 0x33, 0x20, 0x4f, 0x19, 0xf6, 0x9c, 0x6c, + 0x2e, 0xd9, 0x68, 0x95, 0xb0, 0xe2, 0x18, 0x06, 0xe5, 0x84, 0x8e, 0xf7, + 0xbf, 0x6c, 0x96, 0xa8, 0x9d, 0x37, 0xc7, 0x28, 0xa1, 0x3d, 0x90, 0x8c, + 0x40, 0x3d, 0xe2, 0x51, 0xfd, 0x55, 0x09, 0xf8, 0x83, 0x43, 0x44, 0x4d, + 0x1c, 0x8a, 0x8d, 0x36, 0x84, 0x64, 0xc4, 0xfa, 0x1d, 0x72, 0x04, 0x0b, + 0x1d, 0x49, 0x13, 0x88, 0x78, 0x5f, 0x07, 0x9b, 0xc8, 0x01, 0x9c, 0x3c, + 0xfc, 0xff, 0x0f, 0xd5, 0x13, 0xcd, 0x15, 0x98, 0xcc, 0xe6, 0x59, 0x1e, + 0x83, 0x38, 0x8f, 0x6c, 0x75, 0xbe, 0xdf, 0xe9, 0x1b, 0xc5, 0xb9, 0x6b, + 0xa4, 0x5a, 0x0c, 0xae, 0x98, 0x8d, 0x93, 0xfa, 0x76, 0x7f, 0x0d, 0x0b, + 0xe8, 0xa0, 0x3b, 0x9e, 0x5e, 0xc8, 0xa8, 0xcc, 0x02, 0xc9, 0x86, 0x9c, + 0x78, 0xaf, 0x6e, 0x6a, 0xf4, 0xfe, 0x49, 0xad, 0xc5, 0x93, 0xae, 0x62, + 0xbd, 0xe3, 0x3a, 0xa8, 0xf2, 0x60, 0xb5, 0x29, 0xde, 0x5f, 0x12, 0x02, + 0x2d, 0x43, 0x90, 0xf5, 0x9d, 0x9d, 0x97, 0x29, 0xfa, 0xdd, 0x60, 0x41, + 0x64, 0xb7, 0xa5, 0x03, 0x72, 0x10, 0x2b, 0xdd, 0x5b, 0x60, 0xe6, 0xf0, + 0xe1, 0xd7, 0xa5, 0x97, 0xec, 0xb4, 0x9a, 0x4c, 0x3e, 0x16, 0xa2, 0x82, + 0xb3, 0xc3, 0x3f, 0x3e, 0x5d, 0x32, 0xac, 0x5a, 0x40, 0xb4, 0x00, 0xfa, + 0xd9, 0x47, 0xe8, 0x77, 0xa8, 0x96, 0x5c, 0x60, 0x04, 0x9c, 0x5c, 0xdf, + 0x24, 0x3b, 0xa7, 0x4a, 0x58, 0x25, 0x12, 0x9a, 0xa8, 0x7b, 0x3e, 0x14, + 0xc8, 0x06, 0x79, 0x23, 0xea, 0x91, 0x7f, 0xe1, 0x78, 0x41, 0x6c, 0xdb, + 0x8c, 0xeb, 0x66, 0x35, 0x87, 0x87, 0x81, 0x65, 0x2c, 0xef, 0x3a, 0x6e, + 0xae, 0xb3, 0x6c, 0xe9, 0x86, 0x50, 0x6d, 0x89, 0xd6, 0x27, 0x0a, 0xdb, + 0xf8, 0xd4, 0xb8, 0x85, 0x8e, 0x37, 0xa6, 0x56, 0xf7, 0x58, 0x18, 0x4c, + 0x44, 0xcf, 0xeb, 0xc4, 0x79, 0x19, 0xfc, 0x2e, 0x53, 0x18, 0x0e, 0x7b, + 0x51, 0x86, 0xf3, 0x59, 0x13, 0xb2, 0xaf, 0xd3, 0xee, 0xf4, 0xd5, 0xbf, + 0x2c, 0xb8, 0x6d, 0x71, 0x74, 0x7c, 0x67, 0x54, 0xa7, 0x4b, 0x03, 0xa9, + 0x1b, 0x62, 0x95, 0x9f, 0xc3, 0xf0, 0x71, 0x39, 0x2d, 0x26, 0xaf, 0xaf, + 0xa7, 0xa5, 0x58, 0xf8, 0xf8, 0x8a, 0xe0, 0x62, 0x90, 0x3f, 0x72, 0x9d, + 0x21, 0x82, 0x76, 0x3e, 0x4c, 0x5d, 0xe0, 0xb5, 0x67, 0x23, 0xe3, 0x13, + 0x1a, 0x29, 0xa3, 0xda, 0xa4, 0xb4, 0x5c, 0x1d, 0x47, 0xdf, 0xdf, 0xc9, + 0x93, 0x6c, 0xb2, 0xb5, 0x22, 0xb3, 0x47, 0x2b, 0xcf, 0xf0, 0x36, 0x87, + 0x51, 0x3c, 0x79, 0x41, 0x70, 0xbd, 0xea, 0x70, 0xa2, 0x29, 0x90, 0x55, + 0x30, 0x6f, 0x3e, 0x50, 0xc8, 0x38, 0xd6, 0xfa, 0x6f, 0xe3, 0x39, 0x67, + 0x88, 0x52, 0x1f, 0xd3, 0x52, 0xbf, 0x3e, 0x7b, 0x2a, 0xe5, 0x1e, 0xcd, + 0xf9, 0xf1, 0x91, 0x1d, 0x04, 0x61, 0x25, 0xbb, 0xe1, 0x33, 0xe3, 0x66, + 0x46, 0xed, 0x06, 0x8d, 0xc3, 0x4f, 0x20, 0xc6, 0x24, 0xa7, 0xb5, 0x49, + 0x3b, 0xc7, 0xe6, 0xa0, 0x77, 0x58, 0xd9, 0x70, 0xb1, 0xf5, 0xec, 0x94, + 0x19, 0xf3, 0x5b, 0x0f, 0x9a, 0xe4, 0xad, 0x37, 0x81, 0xaf, 0x68, 0x7b, + 0xe5, 0x67, 0xb5, 0xae, 0x7f, 0x2d, 0x64, 0x78, 0x68, 0x5a, 0xd1, 0x8f, + 0x1c, 0xc0, 0xc3, 0x5b, 0x21, 0x77, 0xe4, 0xa8, 0x5d, 0x05, 0x50, 0xc1, + 0x92, 0xee, 0x36, 0x2d, 0xd2, 0xff, 0xee, 0xc2, 0x11, 0x99, 0xee, 0xd7, + 0x48, 0xfb, 0x6a, 0xa3, 0xc9, 0xb7, 0x0c, 0xc1, 0xe5, 0x12, 0xbf, 0x6f, + 0x58, 0x66, 0x35, 0x34, 0x26, 0xaa, 0xbe, 0xc3, 0x33, 0x86, 0xfd, 0xc0, + 0x1c, 0xa5, 0xe4, 0x1e, 0x91, 0xc4, 0x55, 0x4e, 0xf1, 0xcb, 0xd2, 0x0b, + 0xe8, 0x0d, 0x89, 0x6a, 0x00, 0xbd, 0x7b, 0xf5, 0x3d, 0x1a, 0x4a, 0x48, + 0xfc, 0xf0, 0x5b, 0xcd, 0xdb, 0xb2, 0xa0, 0x27, 0x4b, 0x8f, 0xf7, 0x87, + 0x78, 0x13, 0xdb, 0x3f, 0xfb, 0x0b, 0xda, 0x22, 0xb3, 0x2b, 0x3a, 0x38, + 0xd2, 0x29, 0x73, 0x77, 0xb8, 0xd6, 0xec, 0xab, 0xb4, 0xfe, 0xbe, 0xbb, + 0x6e, 0xe2, 0xc8, 0x45, 0x7b, 0x0d, 0x36, 0x28, 0x0f, 0x45, 0x72, 0xea, + 0x6d, 0x38, 0x02, 0x5e, 0x48, 0x89, 0x12, 0x24, 0x1b, 0x33, 0x0f, 0xe9, + 0xf4, 0xce, 0xf8, 0x27, 0x16, 0x37, 0x29, 0xae, 0xe8, 0x22, 0x03, 0x31, + 0xa9, 0xa0, 0x73, 0x0c, 0x40, 0xe4, 0xfc, 0x6b, 0xe2, 0x1c, 0x8d, 0x7c, + 0x40, 0x82, 0x72, 0x28, 0xd0, 0x7d, 0xe5, 0xef, 0x05, 0x14, 0x80, 0x28, + 0x11, 0x32, 0x0d, 0x63, 0x8a, 0xc3, 0x7c, 0xfe, 0xf5, 0x06, 0x0e, 0xb0, + 0x78, 0x5c, 0x3a, 0xb6, 0x54, 0x37, 0x46, 0xa7, 0x43, 0x4f, 0x05, 0xec, + 0xe4, 0x9f, 0xd8, 0x55, 0x1f, 0x70, 0xb3, 0xe6, 0xbc, 0x46, 0x34, 0x9e, + 0xfc, 0xa4, 0x57, 0x8f, 0x0f, 0x25, 0x6f, 0x9f, 0xb3, 0x80, 0x21, 0x0b, + 0xa1, 0xca, 0x59, 0xcd, 0x37, 0xf7, 0xc9, 0xcb, 0xbe, 0x91, 0xad, 0x07, + 0x4f, 0xc7, 0x4e, 0x04, 0xbd, 0x38, 0x8b, 0x63, 0xb5, 0x51, 0xac, 0xc8, + 0x83, 0x3a, 0xa7, 0xe1, 0x77, 0xbc, 0xa4, 0x0c, 0x6c, 0x50, 0xeb, 0x46, + 0xe1, 0x45, 0x9a, 0x7b, 0x01, 0xca, 0x54, 0xf0, 0x0f, 0xa0, 0x1f, 0x43, + 0x9a, 0x19, 0x70, 0x2e, 0x70, 0x5a, 0xcf, 0x3b, 0x1b, 0x41, 0xfd, 0xd3, + 0x9a, 0xa2, 0x36, 0x14, 0xf0, 0xdd, 0xb0, 0x12, 0x6d, 0xcf, 0x55, 0x3f, + 0xef, 0x0a, 0xc1, 0x80, 0xa9, 0x68, 0xc3, 0x98, 0x03, 0x46, 0x34, 0xce, + 0x91, 0xb2, 0x7a, 0x94, 0xd2, 0xe7, 0xb9, 0x9c, 0x56, 0xb8, 0xf8, 0xd6, + 0xff, 0xbf, 0x8b, 0x39, 0x45, 0x04, 0x45, 0xc9, 0xa2, 0xe2, 0xbb, 0x50, + 0x68, 0x13, 0x32, 0x1e, 0x09, 0x51, 0xb7, 0xb9, 0xcf, 0x5f, 0xcc, 0x54, + 0xd2, 0xf3, 0xc1, 0x9d, 0xa0, 0x8d, 0x22, 0xc8, 0x7e, 0x1b, 0xc6, 0x14, + 0xde, 0x5f, 0x52, 0xb4, 0x69, 0x71, 0xca, 0x58, 0x1d, 0x1e, 0x89, 0xcb, + 0x56, 0x78, 0x7a, 0x85, 0xee, 0xfd, 0xf6, 0x7e, 0xbe, 0x49, 0x9b, 0xb1, + 0x05, 0x95, 0x12, 0xe9, 0x63, 0xbd, 0x61, 0x9a, 0x26, 0xf9, 0x0b, 0x9f, + 0x23, 0x0a, 0x59, 0x55, 0x93, 0xd3, 0x2d, 0xca, 0x66, 0x45, 0x03, 0xb7, + 0xf0, 0x88, 0x9e, 0xc1, 0x11, 0xbb, 0x62, 0x2c, 0x6f, 0xac, 0x3e, 0x87, + 0xd7, 0xe6, 0x4a, 0x44, 0x83, 0x04, 0x5d, 0x5d, 0xbc, 0x3c, 0xce, 0x83, + 0x2b, 0x11, 0x42, 0x02, 0x73, 0x1c, 0x24, 0x90, 0xd9, 0x1a, 0x7d, 0x96, + 0x82, 0x33, 0x75, 0x1e, 0x59, 0xea, 0xa7, 0x99, 0xe1, 0x5b, 0xdc, 0xe4, + 0x07, 0xc5, 0x48, 0x07, 0xb4, 0xbc, 0x80, 0x0e, 0xbd, 0x63, 0x6e, 0x66, + 0xf1, 0x12, 0xb6, 0x67, 0xe0, 0x14, 0x74, 0x9f, 0xbb, 0xb3, 0xb8, 0x16, + 0xd0, 0x25, 0xe9, 0x21, 0x80, 0x1a, 0x32, 0xb0, 0x58, 0x9a, 0x62, 0x17, + 0x18, 0x9d, 0x64, 0x2d, 0x47, 0x89, 0x82, 0x3b, 0x8c, 0x5d, 0x60, 0xc4, + 0x54, 0x69, 0xaa, 0xb4, 0x6a, 0x1d, 0x16, 0xb0, 0xe2, 0x5d, 0x7d, 0xeb, + 0xb9, 0x80, 0x37, 0xcd, 0x5b, 0xf0, 0xa1, 0xa8, 0x39, 0xb2, 0xd6, 0x3a, + 0xc8, 0xcd, 0xca, 0xaf, 0xcb, 0x3b, 0x54, 0xc2, 0x67, 0x49, 0xf3, 0xf1, + 0x11, 0x4d, 0x53, 0x7c, 0x46, 0x8d, 0x22, 0xf6, 0x9a, 0x0d, 0x9e, 0xda, + 0x37, 0xc6, 0x06, 0x00, 0xca, 0xb6, 0xb6, 0x99, 0xc5, 0xb6, 0x81, 0x7e, + 0x87, 0x62, 0xcf, 0x07, 0x76, 0xc1, 0x5f, 0xfe, 0x86, 0xfc, 0x5b, 0xa0, + 0xac, 0xca, 0xcb, 0x7d, 0xf5, 0x5a, 0xc2, 0x5e, 0x41, 0x48, 0x35, 0xc4, + 0x71, 0x9d, 0xc4, 0x0a, 0x79, 0x6f, 0xe3, 0x6d, 0x47, 0xd4, 0xaa, 0xfd, + 0x97, 0xe7, 0xb0, 0x7e, 0x61, 0xf1, 0x7d, 0x7e, 0xf8, 0x78, 0x4c, 0x2e, + 0x65, 0x51, 0xeb, 0x99, 0xd0, 0x3e, 0x24, 0x4c, 0xe0, 0x40, 0x7e, 0x2d, + 0xf7, 0x00, 0x9d, 0x50, 0x87, 0xce, 0x1f, 0x9a, 0xd2, 0x76, 0x00, 0x09, + 0xeb, 0x10, 0x1b, 0x4c, 0xf1, 0x43, 0x0e, 0x35, 0xbb, 0x23, 0x2e, 0x26, + 0x3d, 0x66, 0xa3, 0x0f, 0xf6, 0x10, 0x8b, 0x67, 0xce, 0x66, 0xfd, 0xb5, + 0x07, 0xdc, 0x04, 0x69, 0xad, 0xe0, 0x4d, 0xdf, 0xdb, 0x2f, 0x87, 0xf7, + 0xde, 0xc3, 0x77, 0x89, 0x71, 0xfd, 0x70, 0x38, 0xed, 0xe6, 0x27, 0xb1, + 0xbd, 0x94, 0x5f, 0x39, 0x20, 0x72, 0x59, 0xc4, 0x39, 0xd0, 0x20, 0x5d, + 0xe2, 0xe7, 0xe0, 0x00, 0x61, 0xc7, 0x65, 0xbd, 0xef, 0x05, 0xb3, 0xc7, + 0x7e, 0xae, 0xc5, 0x83, 0x7f, 0xc1, 0x32, 0x4e, 0x2a, 0x17, 0x64, 0x4e, + 0x2a, 0x9a, 0x2d, 0x26, 0x99, 0xa2, 0xd7, 0x37, 0x3a, 0x10, 0x6a, 0x89, + 0x72, 0x43, 0x0e, 0x3a, 0x03, 0x4c, 0xf9, 0xfe, 0xe8, 0xfc, 0x87, 0x71, + 0x37, 0x71, 0x5a, 0x05, 0xbc, 0x4e, 0x20, 0x4c, 0xd7, 0xf9, 0x8d, 0x4e, + 0xb8, 0xb8, 0x56, 0x07, 0xc8, 0x6e, 0x34, 0x6d, 0x45, 0x83, 0x34, 0xf0, + 0x77, 0xfb, 0x18, 0xec, 0x72, 0xf6, 0x4c, 0xfb, 0xba, 0x84, 0xe9, 0x89, + 0x3d, 0xfd, 0xb7, 0x0d, 0x70, 0xae, 0xa4, 0x48, 0x6b, 0x39, 0xf8, 0x62, + 0xc0, 0x7f, 0x0c, 0xf2, 0xa3, 0xfa, 0x7a, 0x64, 0x83, 0x57, 0x7d, 0x4c, + 0x04, 0x96, 0xd7, 0x9d, 0x10, 0x8b, 0x34, 0x48, 0x17, 0xff, 0x74, 0x5c, + 0x9c, 0xbe, 0xeb, 0xe5, 0x52, 0x94, 0x6a, 0x34, 0x6f, 0xf7, 0x95, 0x32, + 0x38, 0x5a, 0x9b, 0x08, 0xf6, 0xda, 0x8c, 0x0f, 0x9c, 0x5d, 0x04, 0x45, + 0xd4, 0xe9, 0xa4, 0x7a, 0xc4, 0xfd, 0x70, 0xfe, 0xa1, 0x3d, 0x21, 0xa0, + 0x01, 0xe5, 0x21, 0xca, 0xa7, 0xd9, 0xf1, 0x9f, 0x45, 0xe1, 0xe8, 0x2d, + 0x27, 0xe6, 0x87, 0xc8, 0x0d, 0xad, 0x13, 0xdb, 0xfe, 0x2f, 0xaa, 0x2b, + 0xdc, 0xa6, 0x1a, 0xc9, 0x19, 0x78, 0x1a, 0x1f, 0x10, 0xcf, 0x31, 0xe1, + 0x06, 0x28, 0x66, 0xb3, 0xa7, 0xa2, 0xa6, 0xf1, 0x3b, 0x2d, 0xd3, 0x81, + 0xaf, 0x6f, 0xc9, 0x88, 0x76, 0xe9, 0x83, 0x6c, 0x52, 0xb9, 0x70, 0x51, + 0x87, 0x6b, 0x8b, 0xbd, 0x5b, 0x9c, 0xa9, 0xf3, 0xcb, 0x55, 0xd1, 0x76, + 0x40, 0xe1, 0x90, 0xb9, 0x4c, 0xbd, 0xab, 0x1d, 0xa0, 0x5b, 0x5b, 0x34, + 0x14, 0x2f, 0x87, 0x8f, 0x63, 0xa0, 0x2d, 0x29, 0x4e, 0x50, 0x4b, 0x18, + 0x5f, 0x86, 0xac, 0x1b, 0x93, 0xe9, 0x59, 0x38, 0xa1, 0x2a, 0x36, 0x21, + 0xb2, 0xa4, 0xc0, 0x79, 0xc1, 0x60, 0xfc, 0x0f, 0xbf, 0x99, 0x04, 0x9d, + 0x4b, 0x17, 0x60, 0x5b, 0xcd, 0x78, 0x03, 0xd7, 0x7c, 0x4b, 0x9b, 0x17, + 0x58, 0x24, 0x60, 0xb8, 0x08, 0x92, 0x48, 0x4f, 0x66, 0x42, 0x9a, 0x98, + 0x2a, 0x99, 0x9a, 0x8f, 0xdd, 0xd7, 0x09, 0xf3, 0x22, 0x66, 0x62, 0xef, + 0xe5, 0x64, 0xd3, 0xdf, 0x31, 0xaa, 0x84, 0x4c, 0xa5, 0x3f, 0x4e, 0x27, + 0x48, 0x37, 0x96, 0x63, 0xbf, 0x8d, 0xe1, 0xf0, 0xd1, 0xef, 0x95, 0x1a, + 0xe6, 0xf4, 0x02, 0x61, 0xbf, 0xe3, 0xbc, 0x8b, 0x3d, 0x0b, 0x77, 0x91, + 0xc0, 0x5d, 0xfb, 0xe6, 0x7e, 0xab, 0x5e, 0xc5, 0x1c, 0x5b, 0x16, 0xfd, + 0x88, 0xa4, 0x78, 0x4c, 0x06, 0x77, 0xc3, 0x6e, 0x84, 0x0c, 0xda, 0xbf, + 0xf3, 0x8e, 0xd3, 0x61, 0x65, 0xac, 0xf2, 0x18, 0x70, 0x68, 0x84, 0x6f, + 0x9f, 0x3a, 0x94, 0x81, 0xa6, 0xc7, 0xc3, 0x92, 0xee, 0x4b, 0x20, 0x15, + 0x4e, 0x03, 0x76, 0x51, 0x5b, 0x4e, 0xe1, 0x5c, 0x51, 0x5e, 0x1b, 0x9c, + 0x30, 0x25, 0x79, 0xdd, 0x70, 0x12, 0xec, 0xdc, 0x45, 0x95, 0x45, 0x43, + 0xcd, 0xbb, 0xae, 0xa0, 0x0d, 0x43, 0xb4, 0xc9, 0x8c, 0x62, 0xfd, 0x7b, + 0xed, 0x50, 0x78, 0xb7, 0xa6, 0x94, 0xcb, 0x98, 0xb0, 0xbe, 0x09, 0xd9, + 0x0c, 0xb2, 0xc4, 0x8b, 0x96, 0x93, 0xd9, 0x26, 0xc6, 0x6d, 0x26, 0x93, + 0x32, 0x4e, 0x86, 0x72, 0x74, 0x92, 0x00, 0x72, 0x0b, 0x20, 0xa3, 0x2b, + 0x94, 0xe6, 0x10, 0x56, 0x5a, 0x41, 0x71, 0x92, 0x08, 0xce, 0x6c, 0xc4, + 0x1d, 0x9e, 0x71, 0x82, 0x64, 0x23, 0xe5, 0x15, 0xef, 0x4a, 0x7c, 0x4d, + 0xe3, 0x92, 0xbc, 0xa3, 0xa2, 0x29, 0xb7, 0x46, 0xfa, 0x8f, 0x9f, 0xc2, + 0x5d, 0xe4, 0xc0, 0x9c, 0x3f, 0x40, 0x17, 0xae, 0x44, 0xf3, 0x28, 0x10, + 0x29, 0x24, 0xa9, 0x1c, 0x9e, 0xd2, 0x55, 0x4c, 0xee, 0x45, 0xfe, 0x4a, + 0x45, 0x12, 0xf5, 0xde, 0xc7, 0x64, 0x15, 0xc3, 0x4a, 0x77, 0x63, 0x05, + 0x8d, 0xa6, 0x31, 0xa0, 0xad, 0x64, 0xaf, 0x3c, 0x69, 0x2c, 0x25, 0x78, + 0xae, 0xa0, 0x88, 0x96, 0x8a, 0xc2, 0x9b, 0x8d, 0xee, 0x6f, 0x2e, 0x79, + 0x1f, 0xec, 0x32, 0x35, 0x75, 0x83, 0x19, 0x8b, 0xda, 0xca, 0xd0, 0xaf, + 0x6a, 0x6c, 0x42, 0xe8, 0x81, 0xb5, 0x69, 0x31, 0x0b, 0x7d, 0xbc, 0xd8, + 0xd2, 0xb7, 0x7a, 0x8f, 0xfa, 0xcf, 0x91, 0x07, 0x1f, 0xda, 0xa9, 0x1f, + 0xb7, 0x2d, 0xff, 0x50, 0x15, 0x2a, 0xef, 0x8c, 0xa1, 0xe3, 0x7f, 0x08, + 0x95, 0xf2, 0x99, 0x83, 0x1f, 0x97, 0x71, 0x3e, 0x35, 0x3c, 0x8c, 0xe7, + 0x08, 0xd8, 0xa6, 0x1f, 0x0c, 0xa6, 0x52, 0xdc, 0x73, 0xa0, 0xfc, 0xd2, + 0x73, 0xe9, 0x27, 0x9d, 0xfd, 0x7a, 0x4a, 0x29, 0xd3, 0x12, 0x26, 0x13, + 0x0f, 0xce, 0xea, 0x56, 0x99, 0x61, 0x78, 0x47, 0x2c, 0xa0, 0x16, 0xa0, + 0xe2, 0x64, 0x97, 0x57, 0x31, 0xf0, 0x32, 0x5b, 0x44, 0x93, 0x76, 0x8b, + 0x59, 0x63, 0x5c, 0x5b, 0x0f, 0xe1, 0xe7, 0x74, 0x98, 0x11, 0x2d, 0x90, + 0xe4, 0xde, 0xd4, 0x3a, 0xc2, 0xfd, 0x24, 0xe3, 0x1f, 0x7a, 0xf4, 0x40, + 0xbb, 0x51, 0x92, 0x8f, 0x68, 0x9c, 0x51, 0xab, 0xdc, 0xf6, 0x1e, 0x96, + 0xca, 0x56, 0x5c, 0x92, 0xca, 0xb2, 0x1b, 0x2e, 0x6d, 0x20, 0x28, 0xb3, + 0x0a, 0x8e, 0xfd, 0xa9, 0xa2, 0x38, 0x74, 0x60, 0x37, 0xa6, 0x96, 0x02, + 0x20, 0x8a, 0x9a, 0x2b, 0x8c, 0xb9, 0x6d, 0xec, 0xff, 0xbf, 0x88, 0xbd, + 0x6c, 0xb4, 0x10, 0xbd, 0xfa, 0x5a, 0xeb, 0xb2, 0x6b, 0x74, 0x13, 0x2d, + 0xa5, 0xdb, 0x60, 0x93, 0xc6, 0xed, 0x39, 0x4f, 0xc5, 0x63, 0xe1, 0x9e, + 0x57, 0x1f, 0xe7, 0x47, 0xa4, 0xfb, 0x7f, 0xfa, 0x3a, 0x46, 0x50, 0x3a, + 0xd8, 0xd3, 0x83, 0xf5, 0xe6, 0x5e, 0xf8, 0x09, 0x0d, 0xfa, 0x33, 0xe1, + 0x50, 0xe4, 0x36, 0x3e, 0x0a, 0x5d, 0xe6, 0xf8, 0x2e, 0x17, 0x87, 0x8f, + 0xe1, 0x8c, 0x82, 0x73, 0xbd, 0xdd, 0x3b, 0x77, 0x47, 0x9f, 0x42, 0xd7, + 0xf4, 0x2d, 0x6c, 0xef, 0xcc, 0x22, 0x15, 0x3c, 0xe9, 0x26, 0xea, 0xbc, + 0xee, 0x09, 0xd3, 0xea, 0x84, 0x0f, 0x46, 0xa8, 0xe0, 0xda, 0xc5, 0x57, + 0x02, 0x54, 0xb6, 0x88, 0x2b, 0x37, 0xe5, 0x96, 0xc5, 0x33, 0xb7, 0x45, + 0x5d, 0xb7, 0xc7, 0xfd, 0xa0, 0xfa, 0x85, 0x1b, 0x2f, 0xe1, 0xec, 0x89, + 0xc6, 0xb2, 0x51, 0x71, 0xcb, 0x08, 0x82, 0x3e, 0xc9, 0xed, 0x80, 0x9d, + 0x37, 0x31, 0x9d, 0x15, 0xde, 0x24, 0x6f, 0xbd, 0x0e, 0x73, 0xa2, 0xb8, + 0x7e, 0x29, 0x7e, 0x96, 0xe4, 0xbb, 0xd6, 0x23, 0x17, 0xff, 0x33, 0x97, + 0x9c, 0x87, 0xe0, 0xe5, 0x0f, 0xb9, 0xb6, 0x31, 0x33, 0xad, 0xf8, 0xd8, + 0xdb, 0xa0, 0x71, 0x13, 0xe4, 0x1c, 0xce, 0xd0, 0x7e, 0x65, 0x7b, 0xa0, + 0x38, 0x17, 0x53, 0x4f, 0x71, 0x75, 0x6d, 0x02, 0x61, 0xc4, 0x52, 0xf8, + 0xe4, 0x2e, 0xbc, 0x52, 0xc1, 0xb1, 0x7e, 0x83, 0x0a, 0xa1, 0xd1, 0xcd, + 0x2f, 0xa0, 0x30, 0xfd, 0x41, 0x86, 0x7f, 0x26, 0xd1, 0xe7, 0xfc, 0xd7, + 0xc7, 0x37, 0xe5, 0x11, 0xa6, 0xc0, 0x9a, 0x75, 0x18, 0x04, 0x36, 0xca, + 0x8e, 0x26, 0x7d, 0xcf, 0xa2, 0x6a, 0x94, 0x9b, 0xc4, 0xf7, 0xc7, 0xeb, + 0x51, 0x13, 0xa3, 0x6f, 0x8c, 0x80, 0x5f, 0xae, 0xf0, 0x18, 0xa0, 0x88, + 0xe0, 0x8d, 0xb7, 0x80, 0x4e, 0x8c, 0xec, 0xc8, 0x7b, 0xeb, 0xac, 0x29, + 0xb7, 0x4a, 0x0f, 0x33, 0xdd, 0x9d, 0x89, 0x0a, 0x10, 0xb0, 0xce, 0x74, + 0x59, 0xa2, 0x62, 0x91, 0xc9, 0xac, 0x56, 0xcd, 0x69, 0xd3, 0x01, 0x6d, + 0x51, 0xe7, 0x04, 0xc3, 0xfb, 0xe9, 0x79, 0x1b, 0x72, 0x72, 0x1a, 0x90, + 0x0a, 0x20, 0x55, 0x85, 0xc1, 0x8b, 0xeb, 0x1e, 0x9f, 0x9f, 0x4a, 0x81, + 0x47, 0x97, 0x96, 0xbc, 0xc2, 0xe4, 0xc2, 0xfe, 0xa0, 0x20, 0xda, 0x70, + 0x0c, 0x2b, 0xe2, 0xd4, 0xc8, 0xcb, 0x46, 0x00, 0xb6, 0x7c, 0xfb, 0xbd, + 0x56, 0x94, 0x3d, 0x7f, 0x64, 0xf7, 0x88, 0xb5, 0xa7, 0xfe, 0xbe, 0x64, + 0x8a, 0xe4, 0x00, 0x08, 0x82, 0x5b, 0x8f, 0x98, 0x77, 0x87, 0xda, 0xaf, + 0x16, 0x25, 0x4a, 0x9a, 0xed, 0xfb, 0x50, 0x18, 0x45, 0x46, 0x2b, 0x73, + 0xff, 0xb9, 0xb9, 0xab, 0xa2, 0x8f, 0x3a, 0xaf, 0xc5, 0x0a, 0x14, 0x91, + 0xb2, 0x3f, 0xa6, 0x93, 0xf4, 0x81, 0x20, 0x77, 0xfa, 0x51, 0x79, 0x62, + 0xe8, 0xe6, 0x89, 0x52, 0x39, 0xd5, 0x01, 0xa2, 0x87, 0xa3, 0x53, 0x74, + 0x3c, 0x36, 0x8a, 0xc3, 0xb4, 0x44, 0x3b, 0x15, 0x21, 0xf6, 0xdc, 0x18, + 0x02, 0xd2, 0x57, 0xe5, 0x10, 0xf0, 0x3d, 0x61, 0xa7, 0x16, 0x85, 0x6f, + 0x71, 0x07, 0x75, 0x50, 0x4b, 0x21, 0x53, 0x47, 0x38, 0x35, 0x9e, 0xa7, + 0xd8, 0xfd, 0x74, 0x59, 0x15, 0x32, 0x7b, 0x89, 0xd0, 0x2c, 0xd9, 0xf6, + 0x40, 0x49, 0x79, 0xdc, 0xfb, 0x0a, 0x64, 0x59, 0x9b, 0x17, 0x47, 0x36, + 0xcb, 0xf0, 0xc3, 0xcc, 0x14, 0x8e, 0x1f, 0xa8, 0x12, 0xaa, 0xb7, 0x6a, + 0xba, 0x45, 0xf9, 0xc4, 0x44, 0xe7, 0xb5, 0x7c, 0xdd, 0xbe, 0x16, 0x76, + 0x52, 0x92, 0x3d, 0x78, 0xb7, 0xec, 0x81, 0x96, 0xd8, 0x7f, 0x34, 0x2a, + 0xa2, 0x64, 0x5f, 0xfd, 0xb1, 0x42, 0x4c, 0x79, 0x98, 0xc9, 0x17, 0x48, + 0x74, 0x12, 0x72, 0x2c, 0xde, 0x91, 0x7e, 0xa9, 0x49, 0x2a, 0xcc, 0x5c, + 0x60, 0x05, 0x25, 0x09, 0x72, 0x20, 0x80, 0x42, 0x7b, 0x18, 0xc2, 0xfc, + 0x2a, 0x5e, 0x3e, 0x2d, 0x61, 0xa6, 0xf6, 0x82, 0x42, 0x83, 0x81, 0x66, + 0x4d, 0xa6, 0xe1, 0xf9, 0xf6, 0x48, 0xd4, 0xc8, 0x69, 0xed, 0xee, 0xb5, + 0x7a, 0xcb, 0xf6, 0x0a, 0x76, 0x0e, 0x61, 0x8b, 0xf2, 0x1a, 0x8a, 0xa7, + 0x88, 0xb0, 0x90, 0xd5, 0x23, 0xaa, 0xe0, 0x2b, 0xd6, 0xd0, 0xef, 0x49, + 0x13, 0x88, 0xc7, 0x50, 0xf0, 0x9e, 0xd5, 0x28, 0xe1, 0xaa, 0x1d, 0xaf, + 0xd9, 0x73, 0xb3, 0x9e, 0xa7, 0xd8, 0xfc, 0xb9, 0x22, 0x97, 0x0e, 0x21, + 0xa0, 0xb9, 0xf9, 0xea, 0x1e, 0x95, 0x88, 0xda, 0x85, 0x7c, 0x32, 0x7c, + 0xbd, 0xef, 0xf8, 0x44, 0x25, 0x5f, 0x23, 0xfd, 0x14, 0x78, 0xc6, 0xdb, + 0x86, 0xee, 0xf8, 0xda, 0xc0, 0xae, 0x92, 0x6a, 0x03, 0xa9, 0x0a, 0xee, + 0x4a, 0x22, 0x5a, 0x6c, 0x39, 0xd3, 0x91, 0x7d, 0x91, 0x43, 0xac, 0x79, + 0xad, 0xab, 0xb7, 0x91, 0xb1, 0x20, 0x84, 0x7f, 0x0a, 0xd7, 0xa8, 0x62, + 0x95, 0xab, 0x04, 0xb6, 0xb2, 0xf1, 0xd4, 0xb0, 0xac, 0x52, 0x89, 0xb0, + 0x93, 0xdf, 0xdf, 0x80, 0x26, 0x0c, 0x32, 0x31, 0xb3, 0xba, 0xa1, 0xba, + 0x6f, 0xa3, 0x14, 0x5c, 0xfa, 0x37, 0x3b, 0x6a, 0xf2, 0xc4, 0x34, 0x27, + 0x08, 0x1a, 0xe4, 0xfc, 0x89, 0x58, 0x79, 0x34, 0x36, 0xe4, 0xad, 0x4b, + 0x3f, 0x57, 0x7b, 0xc1, 0x59, 0x2d, 0xb6, 0x54, 0x44, 0xbe, 0x4e, 0x5d, + 0x0d, 0x6a, 0xf3, 0xcd, 0xbf, 0xcd, 0x4d, 0x9f, 0x9a, 0x50, 0x09, 0xa4, + 0x6b, 0x8b, 0xb3, 0x01, 0x69, 0x6c, 0x69, 0x5d, 0x28, 0x73, 0x9e, 0xb5, + 0xc2, 0xc7, 0x6e, 0xff, 0x4c, 0x5c, 0x6b, 0x93, 0x22, 0xc1, 0x9f, 0xa6, + 0x71, 0xbf, 0x4d, 0x2d, 0x4e, 0x4e, 0x98, 0xa3, 0x6d, 0xab, 0x05, 0xa0, + 0xde, 0x34, 0x41, 0x28, 0xa4, 0x38, 0x75, 0x4e, 0xdf, 0x7f, 0xc9, 0xdd, + 0xbf, 0x5a, 0xd4, 0xcd, 0x38, 0x0c, 0x89, 0xe7, 0x0e, 0xfc, 0x0f, 0x27, + 0x39, 0x21, 0xa4, 0xa6, 0x07, 0x7b, 0x2a, 0x13, 0x56, 0xe7, 0x4e, 0x55, + 0x57, 0x71, 0x98, 0xb9, 0x3d, 0x59, 0xb5, 0xa8, 0x24, 0x18, 0x08, 0xa2, + 0x6e, 0x9a, 0xe5, 0x97, 0xa7, 0x38, 0xd9, 0x43, 0x9b, 0x19, 0x17, 0x34, + 0x03, 0xd6, 0xba, 0xe9, 0x71, 0x38, 0x26, 0x90, 0x78, 0x9e, 0x1c, 0x41, + 0x8d, 0x60, 0xdd, 0x0e, 0x12, 0x46, 0x37, 0xb4, 0x79, 0x87, 0x33, 0x12, + 0x24, 0xc4, 0x5a, 0x6c, 0x70, 0xa2, 0xb2, 0x58, 0xbb, 0xe7, 0xd6, 0x88, + 0x42, 0x2d, 0x49, 0xc8, 0x67, 0x1e, 0xc5, 0xed, 0x16, 0xa8, 0x1f, 0x36, + 0x2b, 0xfb, 0x0d, 0x51, 0x96, 0xc8, 0x78, 0xf2, 0xab, 0x82, 0xa1, 0xe2, + 0xaf, 0x8c, 0xa4, 0x13, 0x54, 0x90, 0xf1, 0xe7, 0xbb, 0xd1, 0x09, 0x23, + 0x76, 0x0e, 0x50, 0x32, 0xc5, 0x54, 0xbb, 0x1e, 0x12, 0x5d, 0x59, 0xf3, + 0xe9, 0xc9, 0xa4, 0xaa, 0xbc, 0x13, 0x1d, 0xf0, 0x79, 0x54, 0xae, 0x70, + 0xc0, 0xea, 0xcb, 0x21, 0x32, 0xe6, 0xe6, 0x8e, 0xaa, 0x51, 0x46, 0x25, + 0x1e, 0xf1, 0x3f, 0x9f, 0xf6, 0xff, 0x19, 0x53, 0x97, 0xbc, 0xa2, 0xb6, + 0x91, 0x59, 0x27, 0x1e, 0x39, 0x76, 0x76, 0x02, 0x0b, 0x03, 0x25, 0x6b, + 0x00, 0x02, 0xfa, 0x7d, 0x69, 0x5e, 0xde, 0x64, 0x33, 0xbf, 0xab, 0x3e, + 0x3f, 0x24, 0x32, 0x68, 0xbf, 0x90, 0x8f, 0x0f, 0xc5, 0x36, 0x58, 0x9e, + 0x9b, 0x11, 0xd1, 0x2a, 0x8a, 0x0d, 0xac, 0x3a, 0x23, 0xe2, 0x8e, 0xd6, + 0x0d, 0x4a, 0x8b, 0x45, 0x04, 0x47, 0xd9, 0x5a, 0x46, 0x6c, 0x70, 0x82, + 0xc7, 0x81, 0x67, 0xdc, 0xa6, 0xfa, 0x6a, 0x86, 0xfd, 0x01, 0xed, 0x90, + 0xf6, 0xe6, 0x26, 0x6d, 0xac, 0x52, 0x03, 0x4a, 0x91, 0x08, 0x7b, 0xa5, + 0x9c, 0xca, 0xd3, 0x2d, 0x79, 0xf1, 0xed, 0xcb, 0xaa, 0x8f, 0x77, 0xc8, + 0x17, 0xa8, 0xfb, 0x6c, 0x15, 0x62, 0xab, 0x34, 0xd1, 0xdd, 0x94, 0x3e, + 0xd4, 0x0c, 0x47, 0xed, 0x04, 0x91, 0xd2, 0xd7, 0x98, 0xb4, 0x43, 0x57, + 0xd1, 0x54, 0xef, 0x63, 0xba, 0xe3, 0x8a, 0x72, 0xc5, 0xb9, 0xf4, 0x30, + 0xfa, 0x16, 0x3c, 0xe1, 0xbb, 0xbe, 0x57, 0x90, 0xb9, 0xa1, 0xa0, 0x23, + 0xfa, 0xdd, 0xbe, 0x2f, 0xb3, 0xec, 0x41, 0x8b, 0x64, 0xeb, 0xc5, 0x41, + 0xea, 0xa8, 0x16, 0x76, 0x6f, 0x28, 0xda, 0x2b, 0x5f, 0x03, 0x0b, 0xe8, + 0x1c, 0x29, 0x71, 0xd8, 0x4e, 0x41, 0xdf, 0x39, 0x8e, 0x6a, 0x95, 0x79, + 0x85, 0x9c, 0xa9, 0x79, 0xd9, 0x8f, 0x33, 0xaf, 0x15, 0x3b, 0x5a, 0x82, + 0x56, 0x32, 0x98, 0x0c, 0xf6, 0xf6, 0x64, 0x42, 0xd4, 0x6a, 0x15, 0x0f, + 0xb9, 0x75, 0x22, 0xbd, 0x9a, 0x58, 0xa6, 0x01, 0x3a, 0x63, 0xf0, 0x80, + 0x78, 0x22, 0x80, 0xa0, 0x14, 0xe1, 0x37, 0x6b, 0xd4, 0x99, 0x3f, 0xc2, + 0xba, 0x2b, 0x8f, 0xf3, 0x56, 0xc8, 0x1b, 0xe4, 0x7a, 0x5e, 0x96, 0x60, + 0xee, 0x74, 0x54, 0xb6, 0x6d, 0x5c, 0x3d, 0x3e, 0x05, 0xf0, 0x9a, 0xf6, + 0xcd, 0xdd, 0x06, 0xdb, 0x8c, 0x21, 0xb9, 0xf5, 0x28, 0x57, 0x9c, 0x4f, + 0xb4, 0x08, 0xcf, 0xac, 0x6c, 0xfe, 0x30, 0xaf, 0xa2, 0xef, 0xcf, 0x93, + 0x15, 0xdd, 0x12, 0x16, 0x19, 0x7d, 0xbc, 0x57, 0xd9, 0xce, 0xbe, 0x0e, + 0xfc, 0xe1, 0xf0, 0x4a, 0x7c, 0xaa, 0xbf, 0x20, 0x64, 0x00, 0x34, 0x59, + 0xed, 0xea, 0x12, 0x58, 0x46, 0x4c, 0xc6, 0x2f, 0x77, 0x62, 0x1d, 0x82, + 0x5c, 0xe8, 0x98, 0x0d, 0xef, 0x5c, 0x0e, 0xec, 0x5d, 0x2e, 0x5f, 0xd2, + 0x22, 0x43, 0x2d, 0xe1, 0x02, 0xd5, 0x4a, 0x0a, 0x79, 0x6f, 0xa5, 0xec, + 0x48, 0xaa, 0xee, 0xf8, 0xe3, 0x5f, 0xdd, 0xe7, 0x26, 0x87, 0xb5, 0xc4, + 0xcf, 0xd9, 0x7f, 0xa8, 0xaa, 0xb6, 0xbe, 0xe9, 0x02, 0x49, 0x5d, 0x5f, + 0x81, 0x8b, 0xb9, 0xbd, 0xc0, 0xc9, 0xd5, 0xfe, 0x36, 0x3e, 0x49, 0x56, + 0x63, 0x8b, 0xce, 0xef, 0x48, 0x6e, 0xc0, 0xd4, 0x04, 0x0c, 0x33, 0x45, + 0x6e, 0x97, 0x9e, 0xa3, 0xae, 0xbc, 0xc2, 0xce, 0xdc, 0xe3, 0xff, 0x48, + 0x51, 0x68, 0x89, 0xad, 0xae, 0xc7, 0xd1, 0xde, 0xe2, 0xf9, 0xfe, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, + 0x0c, 0x18, 0x20, 0x24, 0x2f, 0x33, 0x3f +}; +#endif /* MLDSA87_KAT_H */ diff --git a/embedded/ti-c2000-f28p55x/Source/wolf_main.c b/embedded/ti-c2000-f28p55x/Source/wolf_main.c new file mode 100644 index 000000000..697f63c07 --- /dev/null +++ b/embedded/ti-c2000-f28p55x/Source/wolf_main.c @@ -0,0 +1,731 @@ +/* wolf_main.c + * + * 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 + */ + +/* Bare-metal entry point and board support for the wolfCrypt test/benchmark + * on the TI LAUNCHXL-F28P55X (TMS320F28P550SJ, C2000 C28x DSP). + * + * Output: by default printf goes to the CCS console over JTAG (CIO), which + * needs no wiring - good for first light. Define WOLF_C2000_SCI_STDOUT to + * route stdout to SCIA (GPIO28/29), the XDS110 virtual COM, at 115200 8N1 for + * headless runs. + * + * The C28x has no hardware TRNG, so my_rng_seed_gen() is a DEV-ONLY counter + * seed - NOT secure. ML-DSA verify and the hash tests are deterministic and + * do not consume it. + */ + +#include "driverlib.h" +#include "device.h" + +#include +#include +#ifdef WOLF_C2000_SCI_STDOUT +#include +#endif + +#include +#include +#include +#include +#include +#ifdef WOLF_ECC +#include +#include +#include +#endif +#include +#include +#include "mldsa87_kat.h" +#ifdef WOLF_ECC +#include "ecc_p256_kat.h" +#endif + +/* ------------------------------------------------------------------------- */ +/* SCIA console (XDS110 virtual COM) */ +/* ------------------------------------------------------------------------- */ +static void c2000_sciInit(void) +{ + /* RX pin */ + GPIO_setPinConfig(DEVICE_GPIO_CFG_SCIRXDA); + GPIO_setDirectionMode(DEVICE_GPIO_PIN_SCIRXDA, GPIO_DIR_MODE_IN); + GPIO_setPadConfig(DEVICE_GPIO_PIN_SCIRXDA, GPIO_PIN_TYPE_STD); + GPIO_setQualificationMode(DEVICE_GPIO_PIN_SCIRXDA, GPIO_QUAL_ASYNC); + + /* TX pin */ + GPIO_setPinConfig(DEVICE_GPIO_CFG_SCITXDA); + GPIO_setDirectionMode(DEVICE_GPIO_PIN_SCITXDA, GPIO_DIR_MODE_OUT); + GPIO_setPadConfig(DEVICE_GPIO_PIN_SCITXDA, GPIO_PIN_TYPE_STD); + GPIO_setQualificationMode(DEVICE_GPIO_PIN_SCITXDA, GPIO_QUAL_ASYNC); + + SCI_performSoftwareReset(SCIA_BASE); + SCI_setConfig(SCIA_BASE, DEVICE_LSPCLK_FREQ, 115200, + (SCI_CONFIG_WLEN_8 | SCI_CONFIG_STOP_ONE | SCI_CONFIG_PAR_NONE)); + SCI_resetChannels(SCIA_BASE); + SCI_resetRxFIFO(SCIA_BASE); + SCI_resetTxFIFO(SCIA_BASE); + SCI_enableFIFO(SCIA_BASE); + SCI_enableModule(SCIA_BASE); + SCI_performSoftwareReset(SCIA_BASE); +} + +/* RAM capture buffer: every stdout byte is mirrored here so the host can read + * program output back over JTAG (symbol g_log / g_logpos), independent of SCI + * routing or CIO. Lives in .bss (RAM); survives a warm reset. The full ML-DSA + * sign build needs the RAM for two key structs, so use a smaller capture + * buffer there (the log only ever holds a few KB of text). */ +#ifdef WOLF_MLDSA_SIGN +volatile char g_log[2048]; +#else +volatile char g_log[12288]; +#endif +volatile unsigned long g_logpos = 0; + +#ifdef WOLF_STACK_PROFILE +/* Stack high-water profiling for the ML-DSA-87 verify path. The C28x SP grows + * UP from the base of the .stack section (RAMLS_STACK 0x8000..0xC000). Paint + * the as-yet-unused upper stack with a sentinel just before the call, then scan + * from the top down afterwards to find the deepest address touched. */ +#define WOLF_STK_BASE 0x8000UL +#define WOLF_STK_TOP 0xC000UL +volatile unsigned long g_stk_paint = 0; /* address paint started from */ +volatile unsigned long g_stk_peak = 0; /* highest address left touched */ +static void wolf_paint_stack(void) +{ + unsigned int marker; + unsigned int* p = &marker + 8; /* just above this frame */ + unsigned int* top = (unsigned int*)WOLF_STK_TOP; + g_stk_paint = (unsigned long)▮ + while (p < top) { + *p = 0xCCCCU; + p++; + } +} +static void wolf_measure_stack(void) +{ + unsigned int* p = (unsigned int*)(WOLF_STK_TOP - 1UL); + unsigned int* base = (unsigned int*)WOLF_STK_BASE; + while ((p > base) && (*p == 0xCCCCU)) { + p--; + } + g_stk_peak = (unsigned long)p; +} +#endif /* WOLF_STACK_PROFILE */ + +static void wolf_logbyte(char c) +{ + if (g_logpos < (unsigned long)sizeof(g_log)) { + g_log[g_logpos++] = c; + } +} + +#ifdef WOLF_C2000_SCI_STDOUT +/* Minimal CGT low-level I/O device that writes to SCIA, so printf/stdout can + * be redirected with add_device()/freopen(). Only write() does real work. */ +int WOLF_open(const char *path, unsigned flags, int llv_fd); +int WOLF_close(int dev_fd); +int WOLF_read(int dev_fd, char *buf, unsigned count); +int WOLF_write(int dev_fd, const char *buf, unsigned count); +fpos_t WOLF_lseek(int dev_fd, fpos_t offset, int origin); +int WOLF_unlink(const char *path); +int WOLF_rename(const char *old_name, const char *new_name); + +int WOLF_open(const char *path, unsigned flags, int llv_fd) +{ + (void)path; (void)flags; (void)llv_fd; + return 0; +} +int WOLF_close(int dev_fd) { (void)dev_fd; return 0; } +int WOLF_read(int dev_fd, char *buf, unsigned count) +{ + (void)dev_fd; (void)buf; (void)count; + return 0; +} +int WOLF_write(int dev_fd, const char *buf, unsigned count) +{ + unsigned i; + (void)dev_fd; + for (i = 0; i < count; i++) { + wolf_logbyte(buf[i]); + if (buf[i] == '\n') { + SCI_writeCharBlockingFIFO(SCIA_BASE, (uint16_t)'\r'); + } + SCI_writeCharBlockingFIFO(SCIA_BASE, (uint16_t)(buf[i] & 0xFF)); + } + return (int)count; +} +fpos_t WOLF_lseek(int dev_fd, fpos_t offset, int origin) +{ + (void)dev_fd; (void)offset; (void)origin; + return (fpos_t)0; +} +int WOLF_unlink(const char *path) { (void)path; return 0; } +int WOLF_rename(const char *old_name, const char *new_name) +{ + (void)old_name; (void)new_name; + return 0; +} + +static void c2000_stdoutToSci(void) +{ + add_device("wolf", _SSA, WOLF_open, WOLF_close, WOLF_read, WOLF_write, + WOLF_lseek, WOLF_unlink, WOLF_rename); + freopen("wolf:", "w", stdout); + setvbuf(stdout, NULL, _IONBF, 0); /* unbuffered: lines appear promptly */ +} +#endif /* WOLF_C2000_SCI_STDOUT */ + +/* ------------------------------------------------------------------------- */ +/* Benchmark time source - free-running CPU Timer 0 at SYSCLK */ +/* ------------------------------------------------------------------------- */ +static void c2000_timerInit(void) +{ + CPUTimer_stopTimer(CPUTIMER0_BASE); + CPUTimer_setPeriod(CPUTIMER0_BASE, 0xFFFFFFFFUL); + CPUTimer_setPreScaler(CPUTIMER0_BASE, 0U); + CPUTimer_setEmulationMode(CPUTIMER0_BASE, + CPUTIMER_EMULATIONMODE_RUNFREE); + CPUTimer_reloadTimerCounter(CPUTIMER0_BASE); + CPUTimer_startTimer(CPUTIMER0_BASE); +} + +/* benchmark.c (WOLFSSL_USER_CURRTIME) calls this for elapsed seconds. + * CPU Timer 0 is a 32-bit down-counter that auto-reloads from 0xFFFFFFFF; we + * accumulate in 64 bits across reloads. NOTE: a single measured interval must + * be shorter than 2^32 / SYSCLK (~28.6 s at 150 MHz) for the wrap handling to + * be exact - true for all BENCH_EMBEDDED cases here. */ +double current_time(int reset) +{ + static unsigned long long accum = 0; + static uint32_t last = 0; + static int started = 0; + uint32_t now; + + now = CPUTimer_getTimerCount(CPUTIMER0_BASE); + + if (!started || reset) { + accum = 0; + last = now; + started = 1; + return 0.0; + } + + if (last >= now) { + accum += (unsigned long long)(last - now); + } + else { + /* counter reloaded once since the last sample */ + accum += (unsigned long long)last + + (0xFFFFFFFFULL - (unsigned long long)now) + 1ULL; + } + last = now; + + return (double)accum / (double)DEVICE_SYSCLK_FREQ; +} + +/* ------------------------------------------------------------------------- */ +/* wolfSSL port hooks (referenced from user_settings.h) */ +/* ------------------------------------------------------------------------- */ +/* XTIME stub - hashing and ML-DSA verify never use wall-clock time. */ +long my_time(long* t) +{ + if (t != NULL) { + *t = 0; + } + return 0; +} + +/* The RNG now uses the real SHA-256 Hash-DRBG seeded by WOLFSSL_GENSEED_FORTEST + * (random.c's built-in test seed) - see user_settings.h. Switching off the old + * WC_NO_HASHDRBG custom-stub RNG (which leaked heap on every wc_InitRng) is what + * lets wolfcrypt_test and the benchmark both run in one image. */ + +#ifdef WOLF_ECC +/* ECDSA P-256 + ECDH bring-up on the C28x (SP single-precision math): + * 1. RNG-free verify KAT (RFC 6979 raw r/s; no ASN). + * 2. keygen + sign + verify round-trip (uses the test DRBG). + * 3. ECDH shared-secret agreement (both directions must match). + */ +static void wolf_ecc_test(void) +{ + /* ecc_key/WC_RNG are large under SP_NO_MALLOC; keep them off the stack so + * the SP point-math call tree has the full 16 KW stack to work in. */ + static ecc_key key; + static ecc_key keyA; + static ecc_key keyB; + static WC_RNG rng; + mp_int r; + mp_int s; + byte secretA[32]; + byte secretB[32]; + word32 lenA; + word32 lenB; + int ret; + int res; + int verified; + int ok; + word32 i; + + /* 1. Deterministic verify KAT (no RNG; raw r/s -> no ASN/DER). */ + res = 0; + ret = wc_ecc_init(&key); + if (ret == 0) { + ret = wc_ecc_import_unsigned(&key, (byte*)kat_p256_qx, + (byte*)kat_p256_qy, NULL, ECC_SECP256R1); + } + if (ret == 0) { + ret = mp_init(&r); + } + if (ret == 0) { + ret = mp_init(&s); + } + if (ret == 0) { + ret = mp_read_unsigned_bin(&r, kat_p256_r, (int)sizeof(kat_p256_r)); + } + if (ret == 0) { + ret = mp_read_unsigned_bin(&s, kat_p256_s, (int)sizeof(kat_p256_s)); + } + if (ret == 0) { + ret = wc_ecc_verify_hash_ex(&r, &s, kat_p256_hash, + (word32)sizeof(kat_p256_hash), &res, &key); + } + printf("ECDSA P-256 verify KAT: %s (ret=%d res=%d)\r\n", + (ret == 0 && res == 1) ? "PASS" : "FAIL", ret, res); + mp_clear(&r); + mp_clear(&s); + wc_ecc_free(&key); + + /* 2. keygen + sign + verify round-trip. */ + res = 0; + verified = 0; + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_ecc_init(&keyA); + } + if (ret == 0) { + ret = wc_ecc_make_key_ex(&rng, 32, &keyA, ECC_SECP256R1); + } + if (ret == 0) { + ret = wc_ecc_set_rng(&keyA, &rng); + } + if (ret == 0) { + ret = mp_init(&r); + } + if (ret == 0) { + ret = mp_init(&s); + } + if (ret == 0) { + ret = wc_ecc_sign_hash_ex(kat_p256_hash, + (word32)sizeof(kat_p256_hash), &rng, &keyA, &r, &s); + } + if (ret == 0) { + ret = wc_ecc_verify_hash_ex(&r, &s, kat_p256_hash, + (word32)sizeof(kat_p256_hash), &verified, &keyA); + } + printf("ECDSA P-256 keygen/sign/verify: %s (ret=%d res=%d)\r\n", + (ret == 0 && verified == 1) ? "PASS" : "FAIL", ret, verified); + mp_clear(&r); + mp_clear(&s); + + /* 3. ECDH: a second key + shared secret both ways must agree. */ + ret = wc_ecc_init(&keyB); + if (ret == 0) { + ret = wc_ecc_make_key_ex(&rng, 32, &keyB, ECC_SECP256R1); + } + if (ret == 0) { + ret = wc_ecc_set_rng(&keyB, &rng); + } + lenA = (word32)sizeof(secretA); + lenB = (word32)sizeof(secretB); + if (ret == 0) { + ret = wc_ecc_shared_secret(&keyA, &keyB, secretA, &lenA); + } + if (ret == 0) { + ret = wc_ecc_shared_secret(&keyB, &keyA, secretB, &lenB); + } + ok = (ret == 0) && (lenA == lenB) && (lenA > 0); + for (i = 0; ok && (i < lenA); i++) { + if (secretA[i] != secretB[i]) { + ok = 0; + } + } + printf("ECDH P-256 shared secret: %s (ret=%d len=%lu)\r\n", + ok ? "PASS" : "FAIL", ret, (unsigned long)lenA); + wc_ecc_free(&keyB); + wc_ecc_free(&keyA); + wc_FreeRng(&rng); +} +#endif /* WOLF_ECC */ + +/* ------------------------------------------------------------------------- */ +/* main */ +/* ------------------------------------------------------------------------- */ +int main(void) +{ +#ifndef NO_CRYPT_TEST + wc_test_ret_t test_ret; +#endif +#ifndef NO_CRYPT_BENCHMARK + int bench_ret; +#endif + + /* PLL to 150 MHz, flash wait states, disable watchdog, enable clocks. */ + Device_init(); + Device_initGPIO(); + c2000_sciInit(); +#ifdef WOLF_C2000_SCI_STDOUT + c2000_stdoutToSci(); +#endif + c2000_timerInit(); + + /* Unbuffered stdout so output appears immediately and survives a crash, + * whether routed to SCIA or the CCS console (CIO). */ + setvbuf(stdout, NULL, _IONBF, 0); + + printf("\r\n"); + printf("=== wolfSSL wolfCrypt on TI C2000 LAUNCHXL-F28P55X ===\r\n"); + + /* Focused SHA3-256 known-answer test (SHA3-256("abc")), to confirm the + * 16-bit-byte Keccak path is correct on the C28x. */ + { + static const byte kat_msg[3] = { 'a', 'b', 'c' }; + static const byte kat_exp[WC_SHA3_256_DIGEST_SIZE] = { + 0x3a,0x98,0x5d,0xa7,0x4f,0xe2,0x25,0xb2, + 0x04,0x5c,0x17,0x2d,0x6b,0xd3,0x90,0xbd, + 0x85,0x5f,0x08,0x6e,0x3e,0x9d,0x52,0x5b, + 0x46,0xbf,0xe2,0x45,0x11,0x43,0x15,0x32 + }; + wc_Sha3 kat_sha; + byte kat_out[WC_SHA3_256_DIGEST_SIZE]; + int ki; + int kok = 1; + + if (wc_InitSha3_256(&kat_sha, NULL, INVALID_DEVID) == 0) { + (void)wc_Sha3_256_Update(&kat_sha, kat_msg, (word32)sizeof(kat_msg)); + (void)wc_Sha3_256_Final(&kat_sha, kat_out); + wc_Sha3_256_Free(&kat_sha); + printf("SHA3-256(abc)="); + for (ki = 0; ki < (int)sizeof(kat_out); ki++) { + printf("%02x", (unsigned)(kat_out[ki] & 0xFF)); + } + printf("\r\n"); + for (ki = 0; ki < (int)sizeof(kat_out); ki++) { + if (kat_out[ki] != kat_exp[ki]) { + kok = 0; + } + } + printf("SHA3-256 KAT: %s\r\n", kok ? "PASS" : "FAIL"); + } + else { + printf("SHA3-256 KAT: init failed\r\n"); + } + } + + /* SHA-256 multi-block KAT (64 bytes 0x00..0x3f) - exercises the full-block + * input path, not just the single-block Final path. */ + { + static byte s2_msg[64]; + static const byte s2_exp[WC_SHA256_DIGEST_SIZE] = { + 0xfd,0xea,0xb9,0xac,0xf3,0x71,0x03,0x62, + 0xbd,0x26,0x58,0xcd,0xc9,0xa2,0x9e,0x8f, + 0x9c,0x75,0x7f,0xcf,0x98,0x11,0x60,0x3a, + 0x8c,0x44,0x7c,0xd1,0xd9,0x15,0x11,0x08 + }; + wc_Sha256 s2; + byte s2o[WC_SHA256_DIGEST_SIZE]; + int si, sok = 1; + for (si = 0; si < 64; si++) { s2_msg[si] = (byte)si; } + if (wc_InitSha256(&s2) == 0) { + (void)wc_Sha256Update(&s2, s2_msg, 64); + (void)wc_Sha256Final(&s2, s2o); + wc_Sha256Free(&s2); + printf("SHA-256(64)="); + for (si = 0; si < (int)sizeof(s2o); si++) { + printf("%02x", (unsigned)(s2o[si] & 0xFF)); + } + printf("\r\n"); + for (si = 0; si < (int)sizeof(s2o); si++) { + if (s2o[si] != s2_exp[si]) { sok = 0; } + } + printf("SHA-256 (multiblock) KAT: %s\r\n", sok ? "PASS" : "FAIL"); + } + } + + /* SHAKE256 multi-block KAT (256 bytes 0x00..0xff), 32-byte output - + * exercises multi-block absorb (the path ML-DSA's mu/tr use). */ + { + static byte sk_msg[256]; + static const byte sk_exp[32] = { + 0x33,0x6c,0x8a,0xa7,0xf2,0xb0,0x8b,0xda, + 0x6b,0xd7,0x40,0x2c,0xd2,0xea,0x89,0x76, + 0x0b,0x77,0x28,0xa8,0xb3,0x18,0x02,0xb8, + 0x05,0x24,0x75,0x63,0x61,0x16,0x53,0x66 + }; + wc_Shake sk1; + byte o1[32]; + int i, match = 1; + for (i = 0; i < 256; i++) { sk_msg[i] = (byte)i; } + if (wc_InitShake256(&sk1, NULL, INVALID_DEVID) == 0) { + (void)wc_Shake256_Update(&sk1, sk_msg, 256); + (void)wc_Shake256_Final(&sk1, o1, (word32)sizeof(o1)); + printf("SHAKE256(256)="); + for (i = 0; i < 32; i++) { printf("%02x", (unsigned)(o1[i] & 0xFF)); } + printf("\r\n"); + for (i = 0; i < 32; i++) { if (o1[i] != sk_exp[i]) { match = 0; } } + printf("SHAKE256 (multiblock) KAT: %s\r\n", match ? "PASS" : "FAIL"); + wc_Shake256_Free(&sk1); + } + /* Same 256 bytes via 3 Updates (100+100+56) - exercises the + * partial-buffer-fills-to-full absorb across Update calls (ML-DSA's + * mu/tr feed several Updates). Must match the single-Update result. */ + if (wc_InitShake256(&sk1, NULL, INVALID_DEVID) == 0) { + int mu_ok = 1; + (void)wc_Shake256_Update(&sk1, sk_msg, 100); + (void)wc_Shake256_Update(&sk1, sk_msg + 100, 100); + (void)wc_Shake256_Update(&sk1, sk_msg + 200, 56); + (void)wc_Shake256_Final(&sk1, o1, (word32)sizeof(o1)); + for (i = 0; i < 32; i++) { if (o1[i] != sk_exp[i]) { mu_ok = 0; } } + printf("SHAKE256 (split Updates) KAT: %s\r\n", mu_ok ? "PASS" : "FAIL"); + wc_Shake256_Free(&sk1); + } + /* SHAKE256 large hash (100x1024 absorb -> 250-byte multi-block squeeze), + * the exact test.c large-hash scenario, compared to test.c's + * large_digest - validates multi-block absorb + multi-block squeeze on + * the C28x. Skipped in the SIGN build: its ~1.4 KW of static buffers + * would not fit alongside the sign key + 32 KW heap. */ +#ifndef WOLF_MLDSA_SIGN + { + static byte lg_in[1024]; + static byte lg_out[250]; + static const byte lg_exp[114] = { + 0x90,0x32,0x4a,0xcc,0xd1,0xdf,0xb8,0x0b,0x79,0x1f,0xb8,0xc8, + 0x5b,0x54,0xc8,0xe7,0x45,0xf5,0x60,0x6b,0x38,0x26,0xb2,0x0a, + 0xee,0x38,0x01,0xf3,0xd9,0xfa,0x96,0x9f,0x6a,0xd7,0x15,0xdf, + 0xb6,0xc2,0xf4,0x20,0x33,0x44,0x55,0xe8,0x2a,0x09,0x2b,0x68, + 0x2e,0x18,0x65,0x5e,0x65,0x93,0x28,0xbc,0xb1,0x9e,0xe2,0xb1, + 0x92,0xea,0x98,0xac,0x21,0xef,0x4c,0xe1,0xb4,0xb7,0xbe,0x81, + 0x5c,0x1d,0xd3,0xb7,0x17,0xe5,0xbb,0xc5,0x8c,0x68,0xb7,0xfb, + 0xac,0x55,0x8a,0x9b,0x4d,0x91,0xe4,0x9f,0x72,0xbb,0x6e,0x38, + 0xaf,0x21,0x7d,0x21,0xaa,0x98,0x4e,0x75,0xc4,0xb4,0x1c,0x7c, + 0x50,0x45,0x54,0xf9,0xea,0x26 }; + int li, ok; + for (li = 0; li < 1024; li++) { lg_in[li] = (byte)(li & 0xFF); } + if (wc_InitShake256(&sk1, NULL, INVALID_DEVID) == 0) { + for (li = 0; li < 100; li++) + (void)wc_Shake256_Update(&sk1, lg_in, 1024); + (void)wc_Shake256_Final(&sk1, lg_out, (word32)sizeof(lg_out)); + ok = 1; + for (li = 0; li < 114; li++) if (lg_out[li] != lg_exp[li]) ok = 0; + printf("SHAKE256 (large multiblock) KAT: %s\r\n", + ok ? "PASS" : "FAIL"); + wc_Shake256_Free(&sk1); + } + } +#endif /* !WOLF_MLDSA_SIGN */ + } + + /* SHA-512 / SHA-384 multi-block KATs (200 bytes 0x00..0xc7) - exercises the + * octet-wise word64 byte-I/O (input load, 128-bit length, digest store). */ + { + static byte h5_msg[200]; + static const byte sha512_exp[WC_SHA512_DIGEST_SIZE] = { + 0x98,0x60,0x58,0xe9,0x89,0x5e,0x2c,0x2a, + 0xb8,0xf9,0xe8,0xcb,0xdf,0x80,0x1d,0xb1, + 0x2a,0x44,0x84,0x2a,0x56,0xa9,0x1d,0x5a, + 0x4e,0x87,0xb1,0xfc,0x98,0xb2,0x93,0x72, + 0x2c,0x46,0x64,0x14,0x2e,0x42,0xc3,0xc5, + 0x51,0xff,0x89,0x86,0x46,0x26,0x8c,0xd9, + 0x2b,0x84,0xed,0x23,0x0b,0x8c,0x94,0xbe, + 0xd7,0x79,0x8d,0x4f,0x27,0xcd,0x74,0x65 + }; + static const byte sha384_exp[WC_SHA384_DIGEST_SIZE] = { + 0x7e,0xa4,0xbb,0x25,0x34,0xc6,0x70,0x36, + 0xf4,0x9d,0xe7,0xbe,0xb5,0xfe,0x8a,0x24, + 0x78,0xdf,0x04,0xff,0x3f,0xef,0x40,0xa9, + 0xcd,0x49,0x23,0x99,0x9a,0x59,0x0e,0x99, + 0x12,0xdf,0x12,0x97,0x21,0x7c,0xe1,0xa0, + 0x21,0xaa,0x2f,0xb1,0x01,0x34,0x98,0xb8 + }; + wc_Sha512 h512; + wc_Sha384 h384; + byte h5o[WC_SHA512_DIGEST_SIZE]; + int hi, h5ok = 1, h3ok = 1; + for (hi = 0; hi < 200; hi++) { h5_msg[hi] = (byte)(hi & 0xFF); } + if (wc_InitSha512(&h512) == 0) { + (void)wc_Sha512Update(&h512, h5_msg, 200); + (void)wc_Sha512Final(&h512, h5o); + wc_Sha512Free(&h512); + for (hi = 0; hi < WC_SHA512_DIGEST_SIZE; hi++) { + if (h5o[hi] != sha512_exp[hi]) { h5ok = 0; } + } + printf("SHA-512 (multiblock) KAT: %s\r\n", h5ok ? "PASS" : "FAIL"); + } + if (wc_InitSha384(&h384) == 0) { + (void)wc_Sha384Update(&h384, h5_msg, 200); + (void)wc_Sha384Final(&h384, h5o); + wc_Sha384Free(&h384); + for (hi = 0; hi < WC_SHA384_DIGEST_SIZE; hi++) { + if (h5o[hi] != sha384_exp[hi]) { h3ok = 0; } + } + printf("SHA-384 (multiblock) KAT: %s\r\n", h3ok ? "PASS" : "FAIL"); + } + } + + /* ML-DSA-87 verify known-answer test (real pk/msg/sig from test.c). This + * is the primary deliverable: a deterministic, RNG-free verify on HW. + * Key struct is static (large; WOLFSSL_MLDSA_VERIFY_NO_MALLOC pins buffers + * into it). msg matches test.c's mldsa_param_vfy_test: msg[i] = (byte)i. + * Skipped in the SIGN build: its static verify key would not fit alongside + * the sign key + 32 KW heap, and the sign round-trip below also exercises + * verify (of a freshly produced signature). */ +#ifndef WOLF_MLDSA_SIGN + { + static wc_MlDsaKey mldsa_key; + byte md_msg[512]; + int md_i; + int md_res = 0; + int md_ret; + + /* test.c builds this as msg[i] = (byte)i. On an 8-bit-byte host that + * wraps mod 256; a wolfCrypt 'byte' buffer must hold octet values, so + * mask explicitly (a C28x 'byte' is a 16-bit cell and would otherwise + * store 256..511 verbatim, corrupting the octet-wise hash input). */ + for (md_i = 0; md_i < (int)sizeof(md_msg); md_i++) { + md_msg[md_i] = (byte)(md_i & 0xFF); + } + md_ret = wc_MlDsaKey_Init(&mldsa_key, NULL, INVALID_DEVID); + if (md_ret == 0) { + md_ret = wc_MlDsaKey_SetParams(&mldsa_key, WC_ML_DSA_87); + } + if (md_ret == 0) { + md_ret = wc_MlDsaKey_ImportPubRaw(&mldsa_key, kat_mldsa87_pub, + (word32)sizeof(kat_mldsa87_pub)); + } + if (md_ret == 0) { +#ifdef WOLF_STACK_PROFILE + wolf_paint_stack(); +#endif + md_ret = wc_MlDsaKey_VerifyCtx(&mldsa_key, kat_mldsa87_sig, + (word32)sizeof(kat_mldsa87_sig), NULL, 0, md_msg, + (word32)sizeof(md_msg), &md_res); +#ifdef WOLF_STACK_PROFILE + wolf_measure_stack(); +#endif + } + printf("ML-DSA-87 verify KAT: %s (ret=%d res=%d)\r\n", + (md_ret == 0 && md_res == 1) ? "PASS" : "FAIL", md_ret, md_res); +#ifdef WOLF_MLDSA_VERIFY_BENCH + /* Time the deterministic verify (CPU Timer 0 via current_time); 10 ops + * keeps the interval under the ~28 s single-measurement wrap. */ + if ((md_ret == 0) && (md_res == 1)) { + int bi; + int br = 0; + double t; + (void)current_time(1); + for (bi = 0; bi < 10; bi++) { + (void)wc_MlDsaKey_VerifyCtx(&mldsa_key, kat_mldsa87_sig, + (word32)sizeof(kat_mldsa87_sig), NULL, 0, md_msg, + (word32)sizeof(md_msg), &br); + } + t = current_time(0); + printf("ML-DSA-87 verify bench: 10 ops in %.3f s = %.2f ms/op, " + "%.2f ops/sec\r\n", t, (t * 1000.0) / 10.0, 10.0 / t); + } +#endif +#ifdef WOLF_STACK_PROFILE + printf("ML-DSA-87 verify: stack peak=0x%lx used=%lu words (key struct " + "sizeof=%lu words); heap: VERIFY_NO_MALLOC\r\n", + g_stk_peak, (g_stk_peak - WOLF_STK_BASE + 1UL), + (unsigned long)sizeof(mldsa_key)); +#endif + wc_MlDsaKey_Free(&mldsa_key); + } +#endif /* !WOLF_MLDSA_SIGN */ + +#ifdef WOLF_MLDSA_SIGN + /* ML-DSA-87 sign+verify round-trip (keygen -> sign -> verify). Exercises + * the full signer on the C28x. Uses the DEV RNG stub (NOT secure) - this + * proves functional correctness, not security. */ + { + static wc_MlDsaKey sgk; + static byte sg_sig[5000]; + static byte sg_msg[64]; + WC_RNG sg_rng; + word32 sg_sigLen = (word32)sizeof(sg_sig); + int sg_i, sg_res = 0, sg_ret; + + for (sg_i = 0; sg_i < (int)sizeof(sg_msg); sg_i++) { + sg_msg[sg_i] = (byte)(sg_i & 0xFF); + } + sg_ret = wc_InitRng(&sg_rng); + if (sg_ret == 0) { + sg_ret = wc_MlDsaKey_Init(&sgk, NULL, INVALID_DEVID); + } + if (sg_ret == 0) { + sg_ret = wc_MlDsaKey_SetParams(&sgk, WC_ML_DSA_87); + } + if (sg_ret == 0) { + sg_ret = wc_MlDsaKey_MakeKey(&sgk, &sg_rng); + } + printf("ML-DSA-87 MakeKey: ret=%d\r\n", sg_ret); + if (sg_ret == 0) { + sg_ret = wc_MlDsaKey_SignCtx(&sgk, NULL, 0, sg_sig, &sg_sigLen, + sg_msg, (word32)sizeof(sg_msg), &sg_rng); + } + printf("ML-DSA-87 Sign: ret=%d sigLen=%lu\r\n", sg_ret, + (unsigned long)sg_sigLen); + if (sg_ret == 0) { + sg_ret = wc_MlDsaKey_VerifyCtx(&sgk, sg_sig, sg_sigLen, NULL, 0, + sg_msg, (word32)sizeof(sg_msg), &sg_res); + } + printf("ML-DSA-87 sign/verify round-trip: %s (ret=%d res=%d)\r\n", + (sg_ret == 0 && sg_res == 1) ? "PASS" : "FAIL", sg_ret, sg_res); + wc_MlDsaKey_Free(&sgk); + wc_FreeRng(&sg_rng); + } +#endif /* WOLF_MLDSA_SIGN */ + +#ifdef WOLF_ECC + printf("\r\n--- ECDSA/ECDH P-256 (SP) ---\r\n"); + wolf_ecc_test(); +#endif + + printf("SYSCLK %lu Hz, CHAR_BIT %d, sizeof(long)=%d sizeof(long long)=%d\r\n", + (unsigned long)DEVICE_SYSCLK_FREQ, (int)CHAR_BIT, + (int)sizeof(long), (int)sizeof(long long)); + +#ifndef NO_CRYPT_TEST + printf("\r\n--- wolfcrypt_test ---\r\n"); + test_ret = wolfcrypt_test(NULL); + printf("wolfcrypt_test result: %ld\r\n", (long)test_ret); +#endif + +#ifndef NO_CRYPT_BENCHMARK + printf("\r\n--- benchmark_test ---\r\n"); + bench_ret = benchmark_test(NULL); + printf("benchmark_test result: %d\r\n", bench_ret); +#endif + + printf("\r\n=== done ===\r\n"); + + for (;;) { + /* spin */ + } +} diff --git a/embedded/ti-c2000-f28p55x/ccxml/F28P550SJ.ccxml b/embedded/ti-c2000-f28p55x/ccxml/F28P550SJ.ccxml new file mode 100644 index 000000000..c6c30fb83 --- /dev/null +++ b/embedded/ti-c2000-f28p55x/ccxml/F28P550SJ.ccxml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +