diff --git a/.github/workflows/_resolve-wolfssl.yml b/.github/workflows/_resolve-wolfssl.yml new file mode 100644 index 0000000..ccee886 --- /dev/null +++ b/.github/workflows/_resolve-wolfssl.yml @@ -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" diff --git a/.github/workflows/sm-matrix.yml b/.github/workflows/sm-matrix.yml new file mode 100644 index 0000000..a5acdc5 --- /dev/null +++ b/.github/workflows/sm-matrix.yml @@ -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 diff --git a/.github/workflows/sm-sanitizer.yml b/.github/workflows/sm-sanitizer.yml new file mode 100644 index 0000000..225ca1a --- /dev/null +++ b/.github/workflows/sm-sanitizer.yml @@ -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 diff --git a/sm2.c b/sm2.c index d629042..3fabe00 100644 --- a/sm2.c +++ b/sm2.c @@ -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; @@ -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; @@ -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; @@ -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; diff --git a/sm4.c b/sm4.c index f32dc28..b011f23 100644 --- a/sm4.c +++ b/sm4.c @@ -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; @@ -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 } } @@ -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) { @@ -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. @@ -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; } @@ -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. @@ -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. @@ -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. @@ -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; } @@ -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)) { @@ -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)) { diff --git a/sp_sm2_c32.c b/sp_sm2_c32.c index 685573d..c974844 100644 --- a/sp_sm2_c32.c +++ b/sp_sm2_c32.c @@ -1396,7 +1396,7 @@ static int sp_256_proj_point_dbl_sm2_9_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, const sp_point_256* p, sp_digit* t) { int err = FP_WOULDBLOCK; - sp_256_proj_point_dbl_9_ctx* ctx = (sp_256_proj_point_dbl_sm2_9_ctx*)sp_ctx->data; + sp_256_proj_point_dbl_9_ctx* ctx = (sp_256_proj_point_dbl_9_ctx*)sp_ctx->data; typedef char ctx_size_test[sizeof(sp_256_proj_point_dbl_9_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; (void)sizeof(ctx_size_test); @@ -1658,7 +1658,7 @@ static int sp_256_proj_point_add_sm2_9_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, const sp_point_256* p, const sp_point_256* q, sp_digit* t) { int err = FP_WOULDBLOCK; - sp_256_proj_point_add_9_ctx* ctx = (sp_256_proj_point_add_sm2_9_ctx*)sp_ctx->data; + sp_256_proj_point_add_9_ctx* ctx = (sp_256_proj_point_add_9_ctx*)sp_ctx->data; /* Ensure only the first point is the same as the result. */ if (q == r) { @@ -2305,7 +2305,7 @@ static int sp_256_ecc_mulmod_sm2_9_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, const sp_point_256* g, const sp_digit* k, int map, int ct, void* heap) { int err = FP_WOULDBLOCK; - sp_256_ecc_mulmod_sm2_9_ctx* ctx = (sp_256_ecc_mulmod_9_ctx*)sp_ctx->data; + sp_256_ecc_mulmod_9_ctx* ctx = (sp_256_ecc_mulmod_9_ctx*)sp_ctx->data; typedef char ctx_size_test[sizeof(sp_256_ecc_mulmod_9_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; (void)sizeof(ctx_size_test); @@ -5175,6 +5175,8 @@ static int sp_256_ecc_gen_k_sm2_9(WC_RNG* rng, sp_digit* k) } while (err == 0); + ForceZero(buf, sizeof(buf)); + return err; #else (void)rng; @@ -5242,7 +5244,7 @@ int sp_ecc_make_key_sm2_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* hea #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN if (err == MP_OKAY) { - err = sp_256_ecc_mulmod_9(infinity, point, p256_sm2_order, 1, 1, NULL); + err = sp_256_ecc_mulmod_sm2_9(infinity, point, p256_sm2_order, 1, 1, NULL); } if (err == MP_OKAY) { if (sp_256_iszero_9(point->x) || sp_256_iszero_9(point->y)) { @@ -5259,9 +5261,14 @@ int sp_ecc_make_key_sm2_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* hea } #ifdef WOLFSSL_SP_SMALL_STACK + if (k != NULL) { + ForceZero(k, sizeof(sp_digit) * 9); + } XFREE(k, heap, DYNAMIC_TYPE_ECC); /* point is not sensitive, so no need to zeroize */ XFREE(point, heap, DYNAMIC_TYPE_ECC); +#else + ForceZero(k, sizeof(k)); #endif return err; @@ -5294,7 +5301,7 @@ int sp_ecc_make_key_256_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, switch (ctx->state) { case 0: - err = sp_256_ecc_gen_k_9(rng, ctx->k); + err = sp_256_ecc_gen_k_sm2_9(rng, ctx->k); if (err == MP_OKAY) { err = FP_WOULDBLOCK; ctx->state = 1; @@ -5315,8 +5322,8 @@ int sp_ecc_make_key_256_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, break; #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN case 2: - err = sp_256_ecc_mulmod_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, - infinity, ctx->point, p256_sm2_order, 1, 1); + err = sp_256_ecc_mulmod_sm2_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + infinity, ctx->point, p256_sm2_order, 1, 1, heap); if (err == MP_OKAY) { if (sp_256_iszero_9(ctx->point->x) || sp_256_iszero_9(ctx->point->y)) { @@ -5444,8 +5451,17 @@ int sp_ecc_secret_gen_sm2_256(const mp_int* priv, const ecc_point* pub, byte* ou } #ifdef WOLFSSL_SP_SMALL_STACK + if (k != NULL) { + ForceZero(k, sizeof(sp_digit) * 9); + } + if (point != NULL) { + ForceZero(point, sizeof(sp_point_256)); + } XFREE(k, heap, DYNAMIC_TYPE_ECC); XFREE(point, heap, DYNAMIC_TYPE_ECC); +#else + ForceZero(k, sizeof(k)); + ForceZero(point, sizeof(point)); #endif return err; @@ -5822,7 +5838,7 @@ int sp_ecc_sign_sm2_256(const byte* hash, word32 hashLen, WC_RNG* rng, } } - if (i == 0) { + if ((err == MP_OKAY) && (i == 0)) { err = RNG_FAILURE_E; } @@ -5835,7 +5851,7 @@ int sp_ecc_sign_sm2_256(const byte* hash, word32 hashLen, WC_RNG* rng, #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 8 * 9); + ForceZero(d, sizeof(sp_digit) * 8 * 2 * 9); XFREE(d, heap, DYNAMIC_TYPE_ECC); } if (point != NULL) { @@ -5846,7 +5862,6 @@ int sp_ecc_sign_sm2_256(const byte* hash, word32 hashLen, WC_RNG* rng, XMEMSET(x, 0, sizeof(sp_digit) * 2U * 9U); XMEMSET(k, 0, sizeof(sp_digit) * 2U * 9U); XMEMSET(r, 0, sizeof(sp_digit) * 2U * 9U); - XMEMSET(r, 0, sizeof(sp_digit) * 2U * 9U); XMEMSET(tmp, 0, sizeof(sp_digit) * 4U * 2U * 9U); #endif @@ -6197,8 +6212,15 @@ int sp_ecc_check_key_sm2_256(const mp_int* pX, const mp_int* pY, } #ifdef WOLFSSL_SP_SMALL_STACK + if (priv != NULL) { + ForceZero(priv, sizeof(sp_digit) * 9); + } XFREE(pub, heap, DYNAMIC_TYPE_ECC); XFREE(priv, heap, DYNAMIC_TYPE_ECC); +#else + if (privm != NULL) { + ForceZero(priv, sizeof(priv)); + } #endif return err; diff --git a/sp_sm2_c64.c b/sp_sm2_c64.c index d2ffcf1..1599641 100644 --- a/sp_sm2_c64.c +++ b/sp_sm2_c64.c @@ -1219,7 +1219,7 @@ static int sp_256_proj_point_dbl_sm2_5_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, const sp_point_256* p, sp_digit* t) { int err = FP_WOULDBLOCK; - sp_256_proj_point_dbl_5_ctx* ctx = (sp_256_proj_point_dbl_sm2_5_ctx*)sp_ctx->data; + sp_256_proj_point_dbl_5_ctx* ctx = (sp_256_proj_point_dbl_5_ctx*)sp_ctx->data; typedef char ctx_size_test[sizeof(sp_256_proj_point_dbl_5_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; (void)sizeof(ctx_size_test); @@ -1479,7 +1479,7 @@ static int sp_256_proj_point_add_sm2_5_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, const sp_point_256* p, const sp_point_256* q, sp_digit* t) { int err = FP_WOULDBLOCK; - sp_256_proj_point_add_5_ctx* ctx = (sp_256_proj_point_add_sm2_5_ctx*)sp_ctx->data; + sp_256_proj_point_add_5_ctx* ctx = (sp_256_proj_point_add_5_ctx*)sp_ctx->data; /* Ensure only the first point is the same as the result. */ if (q == r) { @@ -2111,7 +2111,7 @@ static int sp_256_ecc_mulmod_sm2_5_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, const sp_point_256* g, const sp_digit* k, int map, int ct, void* heap) { int err = FP_WOULDBLOCK; - sp_256_ecc_mulmod_sm2_5_ctx* ctx = (sp_256_ecc_mulmod_5_ctx*)sp_ctx->data; + sp_256_ecc_mulmod_5_ctx* ctx = (sp_256_ecc_mulmod_5_ctx*)sp_ctx->data; typedef char ctx_size_test[sizeof(sp_256_ecc_mulmod_5_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; (void)sizeof(ctx_size_test); @@ -4933,6 +4933,8 @@ static int sp_256_ecc_gen_k_sm2_5(WC_RNG* rng, sp_digit* k) } while (err == 0); + ForceZero(buf, sizeof(buf)); + return err; #else (void)rng; @@ -5000,7 +5002,7 @@ int sp_ecc_make_key_sm2_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* hea #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN if (err == MP_OKAY) { - err = sp_256_ecc_mulmod_5(infinity, point, p256_sm2_order, 1, 1, NULL); + err = sp_256_ecc_mulmod_sm2_5(infinity, point, p256_sm2_order, 1, 1, NULL); } if (err == MP_OKAY) { if (sp_256_iszero_5(point->x) || sp_256_iszero_5(point->y)) { @@ -5017,9 +5019,14 @@ int sp_ecc_make_key_sm2_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* hea } #ifdef WOLFSSL_SP_SMALL_STACK + if (k != NULL) { + ForceZero(k, sizeof(sp_digit) * 5); + } XFREE(k, heap, DYNAMIC_TYPE_ECC); /* point is not sensitive, so no need to zeroize */ XFREE(point, heap, DYNAMIC_TYPE_ECC); +#else + ForceZero(k, sizeof(k)); #endif return err; @@ -5052,7 +5059,7 @@ int sp_ecc_make_key_256_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, switch (ctx->state) { case 0: - err = sp_256_ecc_gen_k_5(rng, ctx->k); + err = sp_256_ecc_gen_k_sm2_5(rng, ctx->k); if (err == MP_OKAY) { err = FP_WOULDBLOCK; ctx->state = 1; @@ -5073,8 +5080,8 @@ int sp_ecc_make_key_256_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, break; #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN case 2: - err = sp_256_ecc_mulmod_5_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, - infinity, ctx->point, p256_sm2_order, 1, 1); + err = sp_256_ecc_mulmod_sm2_5_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + infinity, ctx->point, p256_sm2_order, 1, 1, heap); if (err == MP_OKAY) { if (sp_256_iszero_5(ctx->point->x) || sp_256_iszero_5(ctx->point->y)) { @@ -5202,8 +5209,17 @@ int sp_ecc_secret_gen_sm2_256(const mp_int* priv, const ecc_point* pub, byte* ou } #ifdef WOLFSSL_SP_SMALL_STACK + if (k != NULL) { + ForceZero(k, sizeof(sp_digit) * 5); + } + if (point != NULL) { + ForceZero(point, sizeof(sp_point_256)); + } XFREE(k, heap, DYNAMIC_TYPE_ECC); XFREE(point, heap, DYNAMIC_TYPE_ECC); +#else + ForceZero(k, sizeof(k)); + ForceZero(point, sizeof(point)); #endif return err; @@ -5580,7 +5596,7 @@ int sp_ecc_sign_sm2_256(const byte* hash, word32 hashLen, WC_RNG* rng, } } - if (i == 0) { + if ((err == MP_OKAY) && (i == 0)) { err = RNG_FAILURE_E; } @@ -5593,7 +5609,7 @@ int sp_ecc_sign_sm2_256(const byte* hash, word32 hashLen, WC_RNG* rng, #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 8 * 5); + ForceZero(d, sizeof(sp_digit) * 8 * 2 * 5); XFREE(d, heap, DYNAMIC_TYPE_ECC); } if (point != NULL) { @@ -5604,7 +5620,6 @@ int sp_ecc_sign_sm2_256(const byte* hash, word32 hashLen, WC_RNG* rng, XMEMSET(x, 0, sizeof(sp_digit) * 2U * 5U); XMEMSET(k, 0, sizeof(sp_digit) * 2U * 5U); XMEMSET(r, 0, sizeof(sp_digit) * 2U * 5U); - XMEMSET(r, 0, sizeof(sp_digit) * 2U * 5U); XMEMSET(tmp, 0, sizeof(sp_digit) * 4U * 2U * 5U); #endif @@ -5951,8 +5966,15 @@ int sp_ecc_check_key_sm2_256(const mp_int* pX, const mp_int* pY, } #ifdef WOLFSSL_SP_SMALL_STACK + if (priv != NULL) { + ForceZero(priv, sizeof(sp_digit) * 5); + } XFREE(pub, heap, DYNAMIC_TYPE_ECC); XFREE(priv, heap, DYNAMIC_TYPE_ECC); +#else + if (privm != NULL) { + ForceZero(priv, sizeof(priv)); + } #endif return err;