Skip to content
Merged
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
37 changes: 37 additions & 0 deletions .github/workflows/_resolve-wolfssl.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Resolve wolfSSL versions

on:
workflow_call:
outputs:
refs:
description: 'JSON array of wolfSSL refs ([latest -stable, master])'
value: ${{ jobs.resolve.outputs.refs }}
latest_stable:
description: 'Latest wolfSSL v*-stable tag resolved at run time'
value: ${{ jobs.resolve.outputs.latest_stable }}

permissions:
contents: read

jobs:
resolve:
name: Resolve wolfSSL version matrix
runs-on: ubuntu-latest
outputs:
refs: ${{ steps.set-matrix.outputs.refs }}
latest_stable: ${{ steps.set-matrix.outputs.latest_stable }}
steps:
- name: Resolve latest -stable wolfSSL tag
id: set-matrix
run: |
set -euo pipefail
LATEST=$(git ls-remote --tags --refs https://github.com/wolfSSL/wolfssl.git 'v*-stable' \
| awk -F/ '{print $NF}' | sort -V | tail -n 1)
if [ -z "${LATEST:-}" ]; then
echo "::error::Could not resolve latest wolfSSL -stable tag from remote"
exit 1
fi
echo "Latest stable wolfSSL: $LATEST"
echo "latest_stable=$LATEST" >> "$GITHUB_OUTPUT"
REFS=$(jq -nc --arg latest "$LATEST" '[$latest, "master"]')
echo "refs=$REFS" >> "$GITHUB_OUTPUT"
88 changes: 88 additions & 0 deletions .github/workflows/sm-matrix.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
name: SM Algorithm Matrix Test

on:
push:
branches: [ '**' ]
pull_request:
branches: [ 'main', 'master', 'release/**' ]
schedule:
- cron: '0 5 * * *'
workflow_dispatch:

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

permissions:
contents: read

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

build:
name: ${{ matrix.config.name }} (wolfSSL ${{ matrix.wolfssl-ref }})
needs: resolve
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
wolfssl-ref: ${{ fromJson(needs.resolve.outputs.refs) }}
config:
- name: default
flags: ''
cflags: ''
- name: sp-c
flags: '--enable-sp'
cflags: ''
- name: sp-asm
flags: '--enable-sp --enable-sp-asm'
cflags: ''
- name: sp-smallstack
flags: '--enable-sp'
cflags: '-DWOLFSSL_SP_SMALL_STACK -DWOLFSSL_SMALL_STACK'
- name: sp-validate-keygen
flags: '--enable-sp'
cflags: '-DWOLFSSL_VALIDATE_ECC_KEYGEN'
env:
SM_FLAGS: >-
--enable-sm3 --enable-sm4-ecb --enable-sm4-cbc --enable-sm4-ctr
--enable-sm4-gcm --enable-sm4-ccm --enable-sm2
steps:
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y autoconf automake libtool

- name: Checkout wolfsm
uses: actions/checkout@v4

- name: Build wolfSSL with wolfsm
run: |
set -euo pipefail
git clone --depth 1 --branch ${{ matrix.wolfssl-ref }} \
https://github.com/wolfSSL/wolfssl.git ../wolfssl
./install.sh ../wolfssl
cd ../wolfssl
./autogen.sh
./configure $SM_FLAGS ${{ matrix.config.flags }} \
CFLAGS="${{ matrix.config.cflags }}"
make -j"$(nproc)"

- name: wolfCrypt test (SM2/SM3/SM4 algorithm self-tests)
working-directory: ../wolfssl
run: ./wolfcrypt/test/testwolfcrypt

- name: SM2 cipher-suite unit test
working-directory: ../wolfssl
run: ./tests/unit.test ./tests/test-sm2.conf

- name: SM benchmark
working-directory: ../wolfssl
run: ./wolfcrypt/benchmark/benchmark -sm2 -sm3 -sm4-cbc -sm4-gcm -sm4-ccm

- name: make check
if: matrix.config.name == 'default'
working-directory: ../wolfssl
run: make check
79 changes: 79 additions & 0 deletions .github/workflows/sm-sanitizer.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: SM Algorithm Sanitizer Test

on:
push:
branches: [ 'master', 'main', 'release/**' ]
pull_request:
branches: [ '**' ]
schedule:
- cron: '0 6 * * *'
workflow_dispatch:

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

permissions:
contents: read

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

sanitizer:
name: ${{ matrix.sanitizer.name }} ${{ matrix.config.name }} (wolfSSL ${{ matrix.wolfssl-ref }})
needs: resolve
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
wolfssl-ref: ${{ fromJson(needs.resolve.outputs.refs) }}
config:
- name: sp-c
cflags: '-DWOLFSSL_SP_SMALL_STACK -DWOLFSSL_SMALL_STACK'
- name: sp-validate-keygen
cflags: '-DWOLFSSL_VALIDATE_ECC_KEYGEN'
sanitizer:
- name: ASan
cflags: '-fsanitize=address -fno-omit-frame-pointer -g -O1'
- name: UBSan
cflags: '-fsanitize=undefined -fno-sanitize-recover=all -fno-omit-frame-pointer -g'
env:
SM_FLAGS: >-
--enable-sm3 --enable-sm4-ecb --enable-sm4-cbc --enable-sm4-ctr
--enable-sm4-gcm --enable-sm4-ccm --enable-sm2 --enable-sp
steps:
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y autoconf automake libtool

- name: Checkout wolfsm
uses: actions/checkout@v4

- name: Build wolfSSL with wolfsm (${{ matrix.sanitizer.name }})
run: |
set -euo pipefail
git clone --depth 1 --branch ${{ matrix.wolfssl-ref }} \
https://github.com/wolfSSL/wolfssl.git ../wolfssl
./install.sh ../wolfssl
cd ../wolfssl
./autogen.sh
./configure $SM_FLAGS \
CFLAGS="${{ matrix.config.cflags }} ${{ matrix.sanitizer.cflags }}"
make -j"$(nproc)"

- name: wolfCrypt test (${{ matrix.sanitizer.name }})
working-directory: ../wolfssl
env:
ASAN_OPTIONS: detect_leaks=0
UBSAN_OPTIONS: halt_on_error=1:print_stacktrace=1
run: ./wolfcrypt/test/testwolfcrypt

- name: SM2 cipher-suite unit test (${{ matrix.sanitizer.name }})
working-directory: ../wolfssl
env:
ASAN_OPTIONS: detect_leaks=0
UBSAN_OPTIONS: halt_on_error=1:print_stacktrace=1
run: ./tests/unit.test ./tests/test-sm2.conf
30 changes: 21 additions & 9 deletions sm2.c
Original file line number Diff line number Diff line change
Expand Up @@ -576,13 +576,17 @@ int wc_ecc_sm2_sign_hash_ex(const byte* hash, word32 hashSz, WC_RNG* rng,
}

#ifdef WOLFSSL_SMALL_STACK
XFREE(pub, key->heap, DYNAMIC_TYPE_ECC);
XFREE(data, key->heap, DYNAMIC_TYPE_ECC);
if (key != NULL) {
XFREE(pub, key->heap, DYNAMIC_TYPE_ECC);
XFREE(data, key->heap, DYNAMIC_TYPE_ECC);
}
#endif
#else
(void)hashSz;

err = NOT_COMPILED_IN;
if (err == MP_OKAY) {
err = NOT_COMPILED_IN;
}
#endif

return err;
Expand Down Expand Up @@ -667,8 +671,10 @@ int wc_ecc_sm2_sign_hash(const byte* hash, word32 hashSz, byte* sig,

#ifdef WOLFSSL_SMALL_STACK
/* Free allocated data. */
XFREE(s, key->heap, DYNAMIC_TYPE_ECC);
XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
if (key != NULL) {
XFREE(s, key->heap, DYNAMIC_TYPE_ECC);
XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
}
#endif

return err;
Expand Down Expand Up @@ -954,12 +960,16 @@ int wc_ecc_sm2_verify_hash_ex(mp_int *r, mp_int *s, const byte *hash,

#ifdef WOLFSSL_SMALL_STACK
/* Free allocated data. */
XFREE(data, key->heap, DYNAMIC_TYPE_ECC);
if (key != NULL) {
XFREE(data, key->heap, DYNAMIC_TYPE_ECC);
}
#endif
#else
(void)hashSz;

err = NOT_COMPILED_IN;
if (err == MP_OKAY) {
err = NOT_COMPILED_IN;
}
#endif

return err;
Expand Down Expand Up @@ -1059,8 +1069,10 @@ int wc_ecc_sm2_verify_hash(const byte* sig, word32 sigSz, const byte* hash,

#ifdef WOLFSSL_SMALL_STACK
/* Free allocated data. */
XFREE(s, key->heap, DYNAMIC_TYPE_ECC);
XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
if (key != NULL) {
XFREE(s, key->heap, DYNAMIC_TYPE_ECC);
XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
}
#endif

return err;
Expand Down
47 changes: 44 additions & 3 deletions sm4.c
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,10 @@ static void sm4_key_schedule(const byte* key, word32* ks)
ks[i] = ks[i - 4] ^ (t ^ rotlFixed(t, 13) ^ rotlFixed(t, 23));
}
#endif
/* Round-key material must not be left on the stack. */
ForceZero(k, sizeof(k));
ForceZero(&t, sizeof(t));
ForceZero(&x, sizeof(x));
#else
word32* ck = sm4_ck;

Expand Down Expand Up @@ -672,11 +676,14 @@ void wc_Sm4Free(wc_Sm4* sm4)
if (sm4 != NULL) {
/* Must zeroize key schedule. */
ForceZero(sm4->ks, sizeof(sm4->ks));
#if defined(WOLFSSL_SM4_CTR)
/* For CBC, tmp is cipher text - no need to zeroize. */
/* For CTR, tmp is encrypted counter that must be zeroized. */
#if defined(WOLFSSL_SM4_CBC) || defined(WOLFSSL_SM4_CTR)
/* CTR keystream and CBC decrypt plaintext both land in tmp. */
ForceZero(sm4->tmp, sizeof(sm4->tmp));
#endif
#ifdef WOLFSSL_SM4_GCM
/* gcm.H is the GHASH subkey derived from the key. */
ForceZero(&sm4->gcm, sizeof(sm4->gcm));
#endif
}
}

Expand Down Expand Up @@ -1232,6 +1239,8 @@ static void sm4_gcm_encrypt_c(wc_Sm4* sm4, byte* out, const byte* in, word32 sz,
in += SM4_BLOCK_SIZE;
c += SM4_BLOCK_SIZE;
}

ForceZero(scratch, sizeof(scratch));
}

if (partial != 0) {
Expand All @@ -1253,6 +1262,9 @@ static void sm4_gcm_encrypt_c(wc_Sm4* sm4, byte* out, const byte* in, word32 sz,
#endif
/* XOR the encrypted initial counter into tag. */
xorbuf(tag, encCounter, tagSz);

ForceZero(counter, sizeof(counter));
ForceZero(encCounter, sizeof(encCounter));
}

/* Decrypt bytes using SM4-GCM implementation in C.
Expand Down Expand Up @@ -1377,6 +1389,11 @@ static int sm4_gcm_decrypt_c(wc_Sm4* sm4, byte* out, const byte* in, word32 sz,
ret = res & SM4_GCM_AUTH_E;
#endif
}

ForceZero(counter, sizeof(counter));
ForceZero(calcTag, sizeof(calcTag));
ForceZero(scratch, sizeof(scratch));

return ret;
}

Expand Down Expand Up @@ -1686,6 +1703,8 @@ static WC_INLINE void sm4_ccm_crypt(wc_Sm4* sm4, byte* out, const byte* in,
/* Copy cipher text out. */
XMEMCPY(out, a, sz);
}

ForceZero(a, sizeof(a));
}

/* Calculate authentication tag for SM4-CCM.
Expand Down Expand Up @@ -1744,6 +1763,9 @@ static WC_INLINE void sm4_ccm_calc_auth_tag(wc_Sm4* sm4, const byte* plain,
sm4_encrypt(sm4->ks, b, t);
/* XOR in other authentication tag data. */
xorbufout(tag, t, a, tagSz);

ForceZero(a, sizeof(a));
ForceZero(t, sizeof(t));
}

/* Encrypt bytes using SM4-CCM implementation in C.
Expand Down Expand Up @@ -1781,6 +1803,8 @@ static void sm4_ccm_encrypt_c(wc_Sm4* sm4, byte* out, const byte* in, word32 sz,
/* Encrypt plaintext to cipher text. */
sm4_ccm_crypt(sm4, out, in, sz, b, ctrSz);
}

ForceZero(b, sizeof(b));
}

/* Decrypt bytes using SM4-CCM implementation in C.
Expand Down Expand Up @@ -1836,6 +1860,9 @@ static int sm4_ccm_decrypt_c(wc_Sm4* sm4, byte* out, const byte* in, word32 sz,
ret = SM4_CCM_AUTH_E;
}

ForceZero(b, sizeof(b));
ForceZero(t, sizeof(t));

return ret;
}

Expand Down Expand Up @@ -1881,6 +1908,13 @@ int wc_Sm4CcmEncrypt(wc_Sm4* sm4, byte* out, const byte* in, word32 sz,
if ((nonceSz < CCM_NONCE_MIN_SZ) || (nonceSz > CCM_NONCE_MAX_SZ)) {
ret = BAD_FUNC_ARG;
}
/* Message length must fit the CCM length field of (15 - nonceSz) bytes. */
if (ret == 0) {
word32 ctrSz = (word32)SM4_BLOCK_SIZE - 1 - nonceSz;
if ((ctrSz < sizeof(sz)) && (sz > (((word32)1 << (8 * ctrSz)) - 1))) {
ret = BAD_FUNC_ARG;
}
}

/* Ensure a key has been set. */
if ((ret == 0) && (!sm4->keySet)) {
Expand Down Expand Up @@ -1943,6 +1977,13 @@ int wc_Sm4CcmDecrypt(wc_Sm4* sm4, byte* out, const byte* in, word32 sz,
if ((nonceSz < CCM_NONCE_MIN_SZ) || (nonceSz > CCM_NONCE_MAX_SZ)) {
ret = BAD_FUNC_ARG;
}
/* Message length must fit the CCM length field of (15 - nonceSz) bytes. */
if (ret == 0) {
word32 ctrSz = (word32)SM4_BLOCK_SIZE - 1 - nonceSz;
if ((ctrSz < sizeof(sz)) && (sz > (((word32)1 << (8 * ctrSz)) - 1))) {
ret = BAD_FUNC_ARG;
}
}

/* Ensure a key has been set. */
if ((ret == 0) && (!sm4->keySet)) {
Expand Down
Loading
Loading