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
88 changes: 88 additions & 0 deletions .github/workflows/sm-aarch64-asm.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
name: SM AArch64 Assembly Test

# The ShangMi code has target specific paths that none of the other workflows
# reach: they all run on x86_64 and none enables WOLFSSL_ARMASM. SM4-GCM in
# particular borrows wolfSSL's GHASH from aes.c, whose ARM build keeps the hash
# subkey in a different representation and reflects it inside the bulk assembly
# rather than in the caller. This job builds for aarch64 and runs the SM
# self-tests there, so that the GHASH subkey handling and the non-12-byte nonce
# path - where the initial counter is itself a GHASH - stay covered.
#
# Built with the aarch64 cross toolchain and run under qemu-user, which is how
# wolfSSL's own multi-arch workflow covers this architecture. A native
# ubuntu-*-arm runner would also work and is faster, at the cost of being a
# different runner pool from every other job here.

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: aarch64 ${{ 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:
# The assembly build is the point of this workflow.
- name: armasm
flags: '--enable-armasm'
- name: armasm-sp-asm
flags: '--enable-armasm --enable-sp --enable-sp-asm'
# Same vectors, same architecture, C code only: tells an assembly
# fault apart from something that is wrong on aarch64 generally.
- name: c-only
flags: ''
env:
SM_FLAGS: >-
--enable-sm3 --enable-sm4-ecb --enable-sm4-cbc --enable-sm4-ctr
--enable-sm4-gcm --enable-sm4-ccm --enable-sm2
QEMU_LD_PREFIX: /usr/aarch64-linux-gnu
steps:
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y autoconf automake libtool \
crossbuild-essential-arm64 qemu-user qemu-user-binfmt

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

- name: Build wolfSSL with wolfsm for aarch64
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 --host=aarch64-linux-gnu CC=aarch64-linux-gnu-gcc \
$SM_FLAGS ${{ matrix.config.flags }}
make -j"$(nproc)"

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

- name: SM benchmark
working-directory: ../wolfssl
run: ./wolfcrypt/benchmark/benchmark -sm2 -sm3 -sm4-cbc -sm4-gcm -sm4-ccm
43 changes: 6 additions & 37 deletions sm4.c
Original file line number Diff line number Diff line change
Expand Up @@ -1248,28 +1248,14 @@ int wc_Sm4CtrEncrypt(wc_Sm4* sm4, byte* out, const byte* in, word32 sz)
*/
static void sm4_gcm_calc_h(wc_Sm4* sm4, byte* iv)
{
#if defined(__aarch64__) && defined(WOLFSSL_ARMASM)
word32* pt = (word32*)sm4->gcm.H;
#endif

/* Encrypt all zeros IV to create hash key for GCM. */
sm4_encrypt(sm4->ks, iv, sm4->gcm.H);
#if !defined(__aarch64__) || !defined(WOLFSSL_ARMASM)
#if defined(GCM_TABLE) || defined(GCM_TABLE_4BIT)
/* Generate table from hash key. */
GenerateM0(&sm4->gcm);
#endif /* GCM_TABLE */
#else
/* Reverse the bits of H for use in assembly. */
__asm__ volatile (
"LD1 {v0.16b}, [%[h]] \n"
"RBIT v0.16b, v0.16b \n"
"ST1 {v0.16b}, [%[out]] \n"
: [out] "=r" (pt)
: [h] "0" (pt)
: "cc", "memory", "v0"
);
#endif
#if defined(GCM_TABLE) || defined(GCM_TABLE_4BIT)
/* Generate table from hash key. Plain H is what GHASH() and GenerateM0()
* take, on every target: aes.c reflects H only inside the bulk assembly
* calls and undoes it before storing. */
Comment thread
SparkiDev marked this conversation as resolved.
GenerateM0(&sm4->gcm);
#endif /* GCM_TABLE */
}

/* Increment counter for GCM.
Expand Down Expand Up @@ -1324,9 +1310,6 @@ static void sm4_gcm_encrypt_c(wc_Sm4* sm4, byte* out, const byte* in, word32 sz,
else {
/* Counter is GHASH of nonce. */
GHASH(&sm4->gcm, NULL, 0, nonce, nonceSz, counter, SM4_BLOCK_SIZE);
#ifdef WOLFSSL_ARMASM
GMULT(counter, sm4->gcm.H);
#endif
}
/* Encrypt the initial counter for GMAC. */
sm4_encrypt(sm4->ks, counter, encCounter);
Expand Down Expand Up @@ -1384,13 +1367,7 @@ static void sm4_gcm_encrypt_c(wc_Sm4* sm4, byte* out, const byte* in, word32 sz,
}

/* Calculate GHASH on additional authentication data and cipher text. */
#ifndef WOLFSSL_ARMASM
GHASH(&sm4->gcm, aad, aadSz, out, sz, tag, tagSz);
#else
GHASH(&sm4->gcm, aad, aadSz, out, sz, counter, SM4_BLOCK_SIZE);
GMULT(counter, sm4->gcm.H);
XMEMCPY(tag, counter, tagSz);
#endif
/* XOR the encrypted initial counter into tag. */
xorbuf(tag, encCounter, tagSz);

Expand Down Expand Up @@ -1437,18 +1414,10 @@ static int sm4_gcm_decrypt_c(wc_Sm4* sm4, byte* out, const byte* in, word32 sz,
else {
/* Counter is GHASH of nonce. */
GHASH(&sm4->gcm, NULL, 0, nonce, nonceSz, counter, SM4_BLOCK_SIZE);
#ifdef WOLFSSL_ARMASM
GMULT(counter, sm4->gcm.H);
#endif
}

/* Calculate GHASH on additional authentication data and cipher text. */
#ifndef WOLFSSL_ARMASM
GHASH(&sm4->gcm, aad, aadSz, in, sz, calcTag, sizeof(calcTag));
#else
GHASH(&sm4->gcm, aad, aadSz, in, sz, calcTag, SM4_BLOCK_SIZE);
GMULT(calcTag, sm4->gcm.H);
#endif
/* Encrypt the initial counter. */
sm4_encrypt(sm4->ks, counter, scratch);
/* XOR the encrypted initial counter into calculated tag. */
Expand Down
Loading