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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
241 changes: 241 additions & 0 deletions .github/workflows/nuvoton-m2354-compile.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
name: "Nuvoton M2354 port"

# Keeps the Nuvoton NuMicro M2354 crypto callback port compiling against the
# real vendor BSP. The port has no autotools option and is not built by any
# other job: an application compiles wolfcrypt/src/port/nuvoton/*.c into its own
# project, the same way wolfcrypt/src/port/st/stm32.c is carried. Without this
# guard a header rename in the BSP, or a refactor in aes.c, ecc.c or cryptocb.h,
# would break the port silently until someone next built for the board.
#
# Nothing is faked. arm-none-eabi-gcc is a plain apt package and the BSP is a
# public GitHub repository, so both legs compile against the genuine Nuvoton
# StdDriver headers at a pinned commit.
#
# secure WOLFSSL_NUVOTON_SECURE, the whole port including nuvoton_hw.c
# nonsecure WOLFSSL_NUVOTON_NSC, where nuvoton_hw.c compiles to nothing
# and the cmse_nonsecure_entry veneers supply the symbols
#
# The runnable example, including those veneers, lives in wolfssl-examples
# under embedded/nuvoton_m2354. Functional correctness is validated on a
# NuMaker-M2354, not here; see wolfcrypt/src/port/nuvoton/README.md.

# START OF COMMON SECTION
on:
push:
branches: [ 'master', 'main', 'release/**' ]
# Same set as the pull_request filter below: a refactor in aes.c, ecc.c or
# cryptocb.h breaks this port just as a change under port/nuvoton does, so
# the post-merge guard has to watch the same tree the PR guard does.
paths:
- 'wolfcrypt/src/**'
- 'wolfssl/wolfcrypt/**'
- '.github/workflows/nuvoton-m2354-compile.yml'
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
branches: [ '**' ]
paths:
- 'wolfcrypt/src/**'
- 'wolfssl/wolfcrypt/**'
- '.github/workflows/nuvoton-m2354-compile.yml'
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read
# END OF COMMON SECTION

env:
# Pinned so a BSP change cannot break a PR that did not touch the port. Bump
# it deliberately.
BSP_REF: 3d423be763edabe1d8b3f27dea363b69e787f8f9

jobs:
compile:
name: ${{ matrix.leg }} (Cortex-M23)
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.draft == false }}
runs-on: ubuntu-24.04
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
include:
- leg: secure
world: WOLFSSL_NUVOTON_SECURE
- leg: nonsecure
world: WOLFSSL_NUVOTON_NSC
steps:
- uses: actions/checkout@v4
name: Checkout wolfSSL

- name: Install the toolchain
run: |
sudo apt-get update
sudo apt-get install -y gcc-arm-none-eabi

- name: Checkout the Nuvoton M2354 BSP
run: |
set -e
# The full repository is around 256 MB and almost none of it is
# needed, so take one commit and only the driver tree.
git clone --filter=blob:none --no-checkout --sparse \
https://github.com/OpenNuvoton/M2354BSP "$GITHUB_WORKSPACE/M2354BSP"
cd "$GITHUB_WORKSPACE/M2354BSP"
git sparse-checkout set \
Library/StdDriver/inc Library/Device Library/CMSIS
git fetch --depth 1 origin "$BSP_REF"
git checkout "$BSP_REF"

- name: Compile the port
run: |
set -e
BSP="$GITHUB_WORKSPACE/M2354BSP"
mkdir -p "$GITHUB_WORKSPACE/cfg"

# Minimal configuration: enough to reach every engine in the port.
# The example in wolfssl-examples carries a realistic one.
cat > "$GITHUB_WORKSPACE/cfg/user_settings.h" <<'EOF'
#ifndef CI_USER_SETTINGS_H
#define CI_USER_SETTINGS_H
#define WOLFSSL_NUVOTON_M2354
#define SINGLE_THREADED
#define NO_FILESYSTEM
#define WOLFSSL_SMALL_STACK
#define WOLFSSL_SHA224
#define WOLFSSL_SHA384
#define WOLFSSL_SHA512
#define HAVE_HASHDRBG
#define HAVE_AES_CBC
#define HAVE_AES_ECB
#define WOLFSSL_AES_DIRECT
#define WOLFSSL_AES_COUNTER
#define HAVE_AESGCM
#define HAVE_ECC
#define HAVE_ECC_DHE
#define HAVE_ECC_SIGN
#define HAVE_ECC_VERIFY
#define HAVE_ECC384
#define WOLFSSL_KEY_GEN
#define TFM_TIMING_RESISTANT
#define ECC_TIMING_RESISTANT
#define WC_RSA_BLINDING
#endif
EOF

CFLAGS="-mcpu=cortex-m23 -mthumb -Os -Wall -Wextra -Werror -c"
CFLAGS="$CFLAGS -I. -I$GITHUB_WORKSPACE/cfg -DWOLFSSL_USER_SETTINGS"
CFLAGS="$CFLAGS -D${{ matrix.world }}"
CFLAGS="$CFLAGS -I$BSP/Library/StdDriver/inc"
CFLAGS="$CFLAGS -I$BSP/Library/Device/Nuvoton/M2354/Include"
CFLAGS="$CFLAGS -I$BSP/Library/CMSIS/Include"

for f in wolfcrypt/src/port/nuvoton/*.c wolfcrypt/src/random.c; do
Comment thread
dgarske marked this conversation as resolved.
echo " $f"
# shellcheck disable=SC2086
arm-none-eabi-gcc $CFLAGS -o /dev/null "$f"
done

- name: Compile reduced configurations
if: ${{ matrix.leg == 'secure' }}
run: |
set -e
# The two full legs above pin one fully-enabled user_settings.h and
# cannot catch a conditional-compilation break. These reduced builds
# exercise the feature guards: verify-only ECC, an RSA-only build
# (mp_tohex gating), the AES-GCM / Key Store opt-outs, and an ECC
# build with every sub-feature off, where the hex and curve-id
# helpers have no caller.
BSP="$GITHUB_WORKSPACE/M2354BSP"
CF="-mcpu=cortex-m23 -mthumb -Os -Wall -Wextra -Wunused-function -Werror -c"
CF="$CF -I. -I$GITHUB_WORKSPACE/rcfg -DWOLFSSL_USER_SETTINGS"
CF="$CF -DWOLFSSL_NUVOTON_SECURE"
CF="$CF -I$BSP/Library/StdDriver/inc"
CF="$CF -I$BSP/Library/Device/Nuvoton/M2354/Include"
CF="$CF -I$BSP/Library/CMSIS/Include"
mkdir -p "$GITHUB_WORKSPACE/rcfg"

build() {
echo "== reduced: $1 =="
for f in wolfcrypt/src/port/nuvoton/*.c wolfcrypt/src/random.c; do
# shellcheck disable=SC2086
arm-none-eabi-gcc $CF -o /dev/null "$f"
done
}

cat > "$GITHUB_WORKSPACE/rcfg/user_settings.h" <<'EOF'
#ifndef RCFG_H
#define RCFG_H
#define WOLFSSL_NUVOTON_M2354
#define SINGLE_THREADED
#define NO_FILESYSTEM
#define HAVE_HASHDRBG
#define WOLFSSL_SHA256
#define HAVE_AES_CBC
#define WOLFSSL_AES_COUNTER
#define HAVE_AESGCM
#define HAVE_ECC
#define HAVE_ECC_DHE
#define HAVE_ECC_VERIFY
#define NO_ECC_SIGN
#define ECC_TIMING_RESISTANT
#define WC_RSA_BLINDING
#endif
EOF
build "verify-only ECC (NO_ECC_SIGN)"

cat > "$GITHUB_WORKSPACE/rcfg/user_settings.h" <<'EOF'
#ifndef RCFG_H
#define RCFG_H
#define WOLFSSL_NUVOTON_M2354
#define SINGLE_THREADED
#define NO_FILESYSTEM
#define HAVE_HASHDRBG
#define WOLFSSL_SHA256
#define NO_ECC
#define WC_RSA_BLINDING
#define WOLFSSL_NUVOTON_RSA
#endif
EOF
build "RSA-only (mp_tohex gating)"

cat > "$GITHUB_WORKSPACE/rcfg/user_settings.h" <<'EOF'
#ifndef RCFG_H
#define RCFG_H
#define WOLFSSL_NUVOTON_M2354
#define SINGLE_THREADED
#define NO_FILESYSTEM
#define HAVE_HASHDRBG
#define WOLFSSL_SHA256
#define HAVE_ECC
#define ECC_TIMING_RESISTANT
#define NO_ECC_SIGN
#define NO_ECC_VERIFY
#define NO_ECC_DHE
#define WC_RSA_BLINDING
#endif
EOF
build "ECC with no sign, verify or DHE"

cat > "$GITHUB_WORKSPACE/rcfg/user_settings.h" <<'EOF'
#ifndef RCFG_H
#define RCFG_H
#define WOLFSSL_NUVOTON_M2354
#define SINGLE_THREADED
#define NO_FILESYSTEM
#define HAVE_HASHDRBG
#define WOLFSSL_SHA256
#define HAVE_AES_CBC
#define WOLFSSL_AES_COUNTER
#define HAVE_ECC
#define HAVE_ECC_DHE
#define HAVE_ECC_SIGN
#define HAVE_ECC_VERIFY
#define ECC_TIMING_RESISTANT
#define WC_RSA_BLINDING
#define WOLFSSL_NUVOTON_NO_AESGCM
#define WOLFSSL_NUVOTON_NO_KS
#endif
EOF
build "no-GCM, no-KS opt-outs"
9 changes: 9 additions & 0 deletions .wolfssl_known_macro_extras
Original file line number Diff line number Diff line change
Expand Up @@ -1060,6 +1060,7 @@ WOLFSSL_NO_RSA_KEY_CHECK
WOLFSSL_NO_SERVER_GROUPS_EXT
WOLFSSL_NO_SESSION_STATS
WOLFSSL_NO_SHA256_N_WAY
WOLFSSL_NO_SHA512_HASHTYPE
WOLFSSL_NO_SHA512_N_WAY
WOLFSSL_NO_SHAKE_N_WAY
WOLFSSL_NO_SIGALG
Expand All @@ -1071,6 +1072,13 @@ WOLFSSL_NO_TRUSTED_CERTS_VERIFY
WOLFSSL_NO_WORD64_OPS
WOLFSSL_NO_XOR_OPS
WOLFSSL_NRF51_AES
WOLFSSL_NUVOTON_NO_AESGCM
WOLFSSL_NUVOTON_NO_HW_MUTEX
WOLFSSL_NUVOTON_NO_KS
WOLFSSL_NUVOTON_NO_SP_DEFAULT
WOLFSSL_NUVOTON_NSC
WOLFSSL_NUVOTON_NSC_IMPL
WOLFSSL_NUVOTON_RNG_OFFLOAD
WOLFSSL_NXP_CASPER_ECC_MUL2ADD
WOLFSSL_NXP_CASPER_ECC_MULMOD
WOLFSSL_NXP_LPC55S6X
Expand Down Expand Up @@ -1232,6 +1240,7 @@ WOLFSSL_ZEPHYR_MAIN_ARGS
WOLF_ALLOW_BUILTIN
WOLF_CONF_ASN_TIME
WOLF_CRYPTO_CB_ASYNC_POLL
WOLF_CRYPTO_CB_ONLY_SHA
WOLF_CRYPTO_CB_SHAKE_XOF
WOLF_CRYPTO_DEV
WOLF_NO_TRAILING_ENUM_COMMAS
Expand Down
75 changes: 45 additions & 30 deletions wolfcrypt/src/asn.c
Original file line number Diff line number Diff line change
Expand Up @@ -34306,29 +34306,6 @@ int DecodeECC_DSA_Sig_Ex(const byte* sig, word32 sigLen, mp_int* r, mp_int* s,

#ifdef WOLFSSL_ASN_TEMPLATE
#if defined(HAVE_ECC) && defined(WOLFSSL_CUSTOM_CURVES)
/* Convert data to hex string.
*
* Big-endian byte array is converted to big-endian hexadecimal string.
*
* @param [in] input Buffer containing data.
* @param [in] inSz Size of data in buffer.
* @param [out] out Buffer to hold hex string.
*/
static void DataToHexString(const byte* input, word32 inSz, char* out)
{
static const char hexChar[] = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
word32 i;

/* Converting a byte of data at a time to two hex characters. */
for (i = 0; i < inSz; i++) {
out[i*2 + 0] = hexChar[input[i] >> 4];
out[i*2 + 1] = hexChar[input[i] & 0xf];
}
/* NUL terminate string. */
out[i * 2] = '\0';
}

#ifndef WOLFSSL_ECC_CURVE_STATIC
/* Convert data to hex string and place in allocated buffer.
*
Expand All @@ -34355,7 +34332,7 @@ static int DataToHexStringAlloc(const byte* input, word32 inSz, char** out,
}
else {
/* Convert to hex string. */
DataToHexString(input, inSz, str);
wc_DataToHexString(input, inSz, str);
*out = str;
}

Expand Down Expand Up @@ -34558,23 +34535,23 @@ static int EccSpecifiedECDomainDecode(const byte* input, word32 inSz,
#else
if (ret == 0) {
/* Base X-ordinate */
DataToHexString(base + 1, (word32)curve->size, (char *)curve->Gx);
wc_DataToHexString(base + 1, (word32)curve->size, (char *)curve->Gx);
/* Base Y-ordinate */
DataToHexString(base + 1 + curve->size, (word32)curve->size, (char *)curve->Gy);
wc_DataToHexString(base + 1 + curve->size, (word32)curve->size, (char *)curve->Gy);
/* Prime */
DataToHexString(dataASN[ECCSPECIFIEDASN_IDX_PRIME_P].data.ref.data,
wc_DataToHexString(dataASN[ECCSPECIFIEDASN_IDX_PRIME_P].data.ref.data,
dataASN[ECCSPECIFIEDASN_IDX_PRIME_P].data.ref.length,
(char *)curve->prime);
/* Parameter A */
DataToHexString(dataASN[ECCSPECIFIEDASN_IDX_PARAM_A].data.ref.data,
wc_DataToHexString(dataASN[ECCSPECIFIEDASN_IDX_PARAM_A].data.ref.data,
dataASN[ECCSPECIFIEDASN_IDX_PARAM_A].data.ref.length,
(char *)curve->Af);
/* Parameter B */
DataToHexString(dataASN[ECCSPECIFIEDASN_IDX_PARAM_B].data.ref.data,
wc_DataToHexString(dataASN[ECCSPECIFIEDASN_IDX_PARAM_B].data.ref.data,
dataASN[ECCSPECIFIEDASN_IDX_PARAM_B].data.ref.length,
(char *)curve->Bf);
/* Order of curve */
DataToHexString(dataASN[ECCSPECIFIEDASN_IDX_ORDER].data.ref.data,
wc_DataToHexString(dataASN[ECCSPECIFIEDASN_IDX_ORDER].data.ref.data,
dataASN[ECCSPECIFIEDASN_IDX_ORDER].data.ref.length,
(char *)curve->order);
}
Expand Down Expand Up @@ -41065,6 +41042,44 @@ int wc_Asn1_PrintAll(Asn1* asn1, Asn1PrintOptions* opts, unsigned char* data,
#endif /* !NO_ASN */

/* Functions that parse, but are not using ASN.1 */

#ifdef WOLFSSL_ASN_HEX_STRING
/* Outside the gate above on purpose: this converts bytes to characters and
* uses no ASN.1, and the hardware ports that reuse it are buildable with
* ASN.1 turned off. asn.h is only included above when ASN.1 is on, so pick up
* the prototype here. */
#include <wolfssl/wolfcrypt/asn.h>

/* Convert data to hex string.
*
* Big-endian byte array is converted to big-endian hexadecimal string.
*
* Written for the custom ECC curve parameters, which SEC 1 carries as byte
* arrays and ecc_set_type holds as strings. Hardware ports whose driver takes
* key material the same way reuse it rather than growing their own copy; see
* WOLFSSL_ASN_HEX_STRING in asn.h. Base16_Decode() goes the other way and
* accepts either case, so the two pair up.
*
* @param [in] input Buffer containing data.
* @param [in] inSz Size of data in buffer.
* @param [out] out Buffer to hold hex string. Needs inSz * 2 + 1 bytes.
*/
void wc_DataToHexString(const byte* input, word32 inSz, char* out)
{
static const char hexChar[] = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
word32 i;

/* Converting a byte of data at a time to two hex characters. */
for (i = 0; i < inSz; i++) {
out[i*2 + 0] = hexChar[input[i] >> 4];
out[i*2 + 1] = hexChar[input[i] & 0xf];
}
/* NUL terminate string. */
out[i * 2] = '\0';
}
#endif /* WOLFSSL_ASN_HEX_STRING */

#if !defined(NO_RSA) && (!defined(NO_BIG_INT) || defined(WOLFSSL_SP_MATH))
/* Software-only import of RSA public key elements (n, e) into RsaKey.
* This internal helper avoids recursion when called from the SETKEY path. */
Expand Down
Loading
Loading