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
12 changes: 11 additions & 1 deletion .github/actions/functest/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ inputs:
cflags:
description: CFLAGS to pass to compilation
default: ""
cross_prefix:
description: Binary prefix for cross compilation
default: ""
exec_wrapper:
description: Binary execution wrapper (e.g. QEMU)
default: ""

runs:
using: composite
Expand All @@ -34,7 +40,11 @@ runs:
gh_token: ${{ inputs.gh_token }}
- name: Functional tests
shell: ${{ env.SHELL }}
env:
CFLAGS: ${{ inputs.cflags }}
CROSS_PREFIX: ${{ inputs.cross_prefix }}
EXEC_WRAPPER: ${{ inputs.exec_wrapper }}
run: |
make clean
CFLAGS="${{ inputs.cflags }}" make test
make test

20 changes: 2 additions & 18 deletions .github/workflows/base.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,8 @@ jobs:
strategy:
fail-fast: false
matrix:
external:
- ${{ github.repository_owner != 'pq-code-package' }}
target:
- runner: pqcp-arm64
- runner: ubuntu-24.04-arm
name: 'aarch64'
- runner: ubuntu-latest
name: 'x86_64'
Expand All @@ -26,12 +24,6 @@ jobs:
- runner: macos-15-intel
name: 'macos (x86_64)'
acvp-version: [v1.1.0.40, v1.1.0.39]
exclude:
- {external: true,
target: {
runner: pqcp-arm64,
name: 'aarch64'
}}
name: Quickcheck (${{ matrix.target.name }}, ACVP ${{ matrix.acvp-version }})
runs-on: ${{ matrix.target.runner }}
steps:
Expand All @@ -44,19 +36,11 @@ jobs:
strategy:
fail-fast: false
matrix:
external:
- ${{ github.repository_owner != 'pq-code-package' }}
target:
- runner: pqcp-arm64
- runner: ubuntu-24.04-arm
name: 'aarch64'
- runner: ubuntu-latest
name: 'x86_64'
exclude:
- {external: true,
target: {
runner: pqcp-arm64,
name: 'aarch64'
}}
name: Quickcheck C90 (${{ matrix.target.name }})
runs-on: ${{ matrix.target.runner }}
steps:
Expand Down
35 changes: 31 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
matrix:
cflags: [ "-Os", "-O3" ]
target:
- runner: pqcp-arm64
- runner: ubuntu-24.04-arm
name: 'aarch64'
archflags: ''
- runner: ubuntu-latest
Expand All @@ -36,13 +36,16 @@ jobs:
darwin: False
- name: gcc-11
shell: ci_gcc11
darwin: True
# TODO: re-enable on macOS (nix gcc fails with duplicate LC_RPATH)
darwin: False
- name: gcc-13
shell: ci_gcc13
darwin: True
# TODO: re-enable on macOS (nix gcc fails with duplicate LC_RPATH)
darwin: False
- name: gcc-14
shell: ci_gcc14
darwin: True
# TODO: re-enable on macOS (nix gcc fails with duplicate LC_RPATH)
darwin: False
- name: clang-18
shell: ci_clang18
darwin: True
Expand Down Expand Up @@ -98,3 +101,27 @@ jobs:
gh_token: ${{ secrets.GITHUB_TOKEN }}
nix-shell: ${{ matrix.compiler.shell }}
cflags: "-std=c99 ${{ matrix.cflags }} ${{ matrix.target.archflags }}"
cross_tests:
name: Cross tests (${{ matrix.target.name }})
strategy:
fail-fast: false
matrix:
target:
- runner: ubuntu-latest
name: 'aarch64_be'
nix_shell: ci-cross-aarch64_be
cross_prefix: aarch64_be-none-linux-gnu-
exec_wrapper: qemu-aarch64_be
cflags: '-static'
runs-on: ${{ matrix.target.runner }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: build+functest (cross)
uses: ./.github/actions/functest
with:
gh_token: ${{ secrets.GITHUB_TOKEN }}
nix-shell: ${{ matrix.target.nix_shell }}
nix-cache: 'true'
cflags: ${{ matrix.target.cflags }}
cross_prefix: ${{ matrix.target.cross_prefix }}
exec_wrapper: ${{ matrix.target.exec_wrapper }}
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ OBJS = $(CSRC:.c=.o)
XTEST ?= xfips205
XTESTC ?= test/xfips205.c

CROSS_PREFIX ?=
CC ?= gcc
CC := $(CROSS_PREFIX)$(CC)
CFLAGS := -Wall \
-Wextra \
-Werror=unused-result \
Expand All @@ -36,7 +38,7 @@ $(XTEST): $(OBJS)
$(CC) $(CFLAGS) -c $^ -o $@

test: $(XTEST)
python3 test/acvp_client.py
EXEC_WRAPPER="$(EXEC_WRAPPER)" python3 test/acvp_client.py

clean:
$(RM) -rf $(XTEST) $(OBJS) *.rsp *.req *.log
Expand Down
4 changes: 4 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
packages.toolchain_riscv64 = util.toolchain_riscv64;
packages.toolchain_riscv32 = util.toolchain_riscv32;
packages.toolchain_ppc64le = util.toolchain_ppc64le;
packages.toolchain_aarch64_be = util.toolchain_aarch64_be;

devShells.default = util.mkShell {
packages = builtins.attrValues
Expand Down Expand Up @@ -106,6 +107,9 @@
devShells.ci-cross-ppc64le = util.mkShell {
packages = builtins.attrValues { inherit (config.packages) linters toolchain_ppc64le; };
};
devShells.ci-cross-aarch64_be = util.mkShell {
packages = builtins.attrValues { inherit (config.packages) linters toolchain_aarch64_be; };
};
devShells.ci-linter = util.mkShellNoCC {
packages = builtins.attrValues { inherit (config.packages) linters; };
};
Expand Down
37 changes: 37 additions & 0 deletions nix/aarch64_be-none-linux-gnu-gcc.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Copyright (c) The mlkem-native project authors
# Copyright (c) The slhdsa-c project authors
# SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT

{ stdenvNoCC
, fetchurl
}:

stdenvNoCC.mkDerivation rec {
pname = "aarch64_be-none-linux-gnu";
version = "10.3.2021.07";

platform = {
x86_64-linux = "x86_64";
}.${stdenvNoCC.hostPlatform.system} or (throw "Unsupported system: ${stdenvNoCC.hostPlatform.system}");

platform_suffix = {
x86_64-linux = "linux-gnu";
}.${stdenvNoCC.hostPlatform.system} or (throw "Unsupported system: ${stdenvNoCC.hostPlatform.system}");

src = fetchurl {
url = "https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64_be-none-linux-gnu.tar.xz";
sha256 = {
x86_64-linux = "sha256-Y8NMrAfOrddGIOqH8nrxqmpvVcIKW8EWryGlndtramo";
}.${stdenvNoCC.hostPlatform.system} or (throw "Unsupported system: ${stdenvNoCC.hostPlatform.system}");
};

dontConfigure = true;
dontBuild = true;
dontPatchELF = true;
dontStrip = true;

installPhase = ''
mkdir -p $out
cp -r * $out
'';
}
7 changes: 7 additions & 0 deletions nix/util.nix
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ rec {
riscv64-gcc = wrap-gcc pkgs.pkgsCross.riscv64;
riscv32-gcc = wrap-gcc pkgs.pkgsCross.riscv32;
ppc64le-gcc = wrap-gcc pkgs.pkgsCross.powernv;
aarch64_be-gcc = (pkgs.callPackage ./aarch64_be-none-linux-gnu-gcc.nix { });
in
# NOTE:
# - native toolchain should be equipped in the shell via `mkShellWithCC` (see `mkShell`)
Expand All @@ -40,6 +41,7 @@ rec {
# - On some machines, `native-gcc` needed to be evaluated lastly (placed as the last element of the toolchain list), or else would result in environment variables (CC, AR, ...) overriding issue.
# pkgs.lib.optionals cross [ pkgs.qemu x86_64-gcc aarch64-gcc riscv64-gcc riscv32-gcc ppc64le-gcc ]
pkgs.lib.optionals cross [ pkgs.qemu ]
++ pkgs.lib.optionals (cross && pkgs.stdenv.isLinux && pkgs.stdenv.isx86_64) [ aarch64_be-gcc ]
++ pkgs.lib.optionals cross [ native-gcc ]
# git is not available in the nix shell on Darwin. As a workaround we add git as a dependency here.
# Initially, we expected this to be fixed by https://github.com/NixOS/nixpkgs/pull/353893, but that does not seem to be the case.
Expand Down Expand Up @@ -135,6 +137,11 @@ rec {
cross_compilers = [ (wrap-gcc pkgs.pkgsCross.powernv) ];
};

toolchain_aarch64_be = _individual_toolchain {
name = "aarch64_be";
cross_compilers = pkgs.lib.optionals (pkgs.stdenv.isLinux && pkgs.stdenv.isx86_64) [ (pkgs.callPackage ./aarch64_be-none-linux-gnu-gcc.nix { }) ];
};

toolchains = pkgs.symlinkJoin {
name = "toolchains";
paths = _toolchains { };
Expand Down
57 changes: 34 additions & 23 deletions sha3_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,35 +25,39 @@ void sha3_init(sha3_var_t *c, size_t md_sz)

void sha3_update(sha3_var_t *c, const void *data, size_t len)
{
size_t i, j;
const uint8_t *in = data;
size_t l;

j = c->pt;
for (i = 0; i < len; i++)
while (len > 0)
{
c->st.b[j++] ^= ((const uint8_t *)data)[i];
if (j >= c->r_sz)
l = c->r_sz - c->pt;
if (l > len)
{
l = len;
}
keccak_f1600_xor_bytes(c->st.d, in, c->pt, l);
c->pt += l;
in += l;
len -= l;
if (c->pt >= c->r_sz)
{
keccak_f1600(c->st.d);
j = 0;
c->pt = 0;
}
}
c->pt = j;
}

/* finalize and output a hash */

void sha3_final(sha3_var_t *c, uint8_t *md)
{
size_t i;
const uint8_t pad = 0x06, pad_end = 0x80;

c->st.b[c->pt] ^= 0x06;
c->st.b[c->r_sz - 1] ^= 0x80;
keccak_f1600_xor_bytes(c->st.d, &pad, c->pt, 1);
keccak_f1600_xor_bytes(c->st.d, &pad_end, c->r_sz - 1, 1);
keccak_f1600(c->st.d);

for (i = 0; i < c->md_sz; i++)
{
md[i] = c->st.b[i];
}
keccak_f1600_extract_bytes(c->st.d, md, 0, c->md_sz);
}

/* compute a SHA-3 hash "md" of "md_sz" bytes from data in "in" */
Expand All @@ -72,29 +76,36 @@ void sha3(uint8_t *md, size_t md_sz, const void *in, size_t in_sz)

void shake_out(sha3_var_t *c, uint8_t *out, size_t out_sz)
{
size_t i, j;
const uint8_t pad = 0x1F, pad_end = 0x80;
size_t l;

/* add padding on the first call */
if (c->md_sz != 0)
{
c->st.b[c->pt] ^= 0x1F;
c->st.b[c->r_sz - 1] ^= 0x80;
keccak_f1600_xor_bytes(c->st.d, &pad, c->pt, 1);
keccak_f1600_xor_bytes(c->st.d, &pad_end, c->r_sz - 1, 1);
keccak_f1600(c->st.d);
c->pt = 0;
c->md_sz = 0;
}

j = c->pt;
for (i = 0; i < out_sz; i++)
while (out_sz > 0)
{
if (j >= c->r_sz)
if (c->pt >= c->r_sz)
{
keccak_f1600(c->st.d);
j = 0;
c->pt = 0;
}
l = c->r_sz - c->pt;
if (l > out_sz)
{
l = out_sz;
}
out[i] = c->st.b[j++];
keccak_f1600_extract_bytes(c->st.d, out, c->pt, l);
c->pt += l;
out += l;
out_sz -= l;
}
c->pt = j;
}

/* compute a SHAKE hash "md" of "md_sz" bytes from data in "in" */
Expand Down
6 changes: 6 additions & 0 deletions sha3_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ extern "C"
/* core permutation */
void keccak_f1600(uint64_t x[25]);

/* byte access to the (native-endian) state */
void keccak_f1600_xor_bytes(uint64_t *state, const uint8_t *data,
size_t offset, size_t length);
void keccak_f1600_extract_bytes(const uint64_t *state, uint8_t *data,
size_t offset, size_t length);

#ifdef __cplusplus
}
#endif
Expand Down
39 changes: 39 additions & 0 deletions sha3_f1600.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,45 @@
uint64_t keccak_f1600_count = 0; /* instrumentation */
#endif

/* byte access to the state; adapted from mlkem-native */

void keccak_f1600_xor_bytes(uint64_t *state, const uint8_t *data, size_t offset,
size_t length)
{
size_t i;
#if defined(SLH_SYS_LITTLE_ENDIAN)
uint8_t *state_ptr = (uint8_t *)state + offset;
for (i = 0; i < length; i++)
{
state_ptr[i] ^= data[i];
}
#else
for (i = 0; i < length; i++)
{
state[(offset + i) >> 3] ^= (uint64_t)data[i]
<< (8 * ((offset + i) & 0x07));
}
#endif
}

void keccak_f1600_extract_bytes(const uint64_t *state, uint8_t *data,
size_t offset, size_t length)
{
size_t i;
#if defined(SLH_SYS_LITTLE_ENDIAN)
const uint8_t *state_ptr = (const uint8_t *)state + offset;
for (i = 0; i < length; i++)
{
data[i] = state_ptr[i];
}
#else
for (i = 0; i < length; i++)
{
data[i] = (state[(offset + i) >> 3] >> (8 * ((offset + i) & 0x07))) & 0xFF;
}
#endif
}

/* forward permutation */

void keccak_f1600(uint64_t x[25])
Expand Down
Loading
Loading