diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index 5aa9a53c8..4dd9c7b12 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -43,7 +43,7 @@ jobs: name: Arm Cortex-A55 (Snapdragon 888) benchmarks bench_pmu: PERF archflags: "-mcpu=cortex-a55 -march=armv8.2-a" - cflags: "-flto -static -DFORCE_AARCH64 -DFIPS202_NATIVE_PROFILE=\"aarch64/profiles/cortex_a55.h\"" + cflags: "-flto -static -DFORCE_AARCH64 -DMLKEM_NATIVE_FIPS202_BACKEND=\\\\\\\"aarch64/cortex_a55.h\\\\\\\"" bench_extra_args: -w exec-on-a55 - system: bpi name: Bananapi bpi-f3 benchmarks diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e0c7e65e7..e63ce068b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -119,6 +119,9 @@ jobs: - name: bring_your_own_fips202 run: | make run -C examples/bring_your_own_fips202 + - name: custom_backend + run: | + make run -C examples/custom_backend build_kat: needs: [quickcheck, quickcheck-windows] strategy: diff --git a/README.md b/README.md index f6f76f7b0..d43c2618a 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ in this repository is for experimental and development purposes only. If you pre ### Can I bring my own backend? Absolutely: You can add further backends for ML-KEM native arithmetic and/or for FIPS-202. Follow the existing backends -as templates. +as templates, or see [examples/custom_backend](examples/custom_backend) for a minimal example how to register a custom backend. ### Can I bring my own FIPS-202? diff --git a/examples/README.md b/examples/README.md index 3412042d1..ba73ec584 100644 --- a/examples/README.md +++ b/examples/README.md @@ -12,3 +12,8 @@ See [mlkem_native_as_code_package](mlkem_native_as_code_package). See [bring_your_own_fips202](bring_your_own_fips202) for an example of how to use mlkem-native with your own FIPS-202 implementation. + +## Using mlkem-native as a code package, custom config + custom FIPS-202 backend + +See [custom_backend](custom_backend) for an example of how to use mlkem-native with a custom configuration file and a +custom FIPS-202 backend. diff --git a/examples/bring_your_own_fips202/Makefile b/examples/bring_your_own_fips202/Makefile index 1a80951e9..e4152b7b0 100644 --- a/examples/bring_your_own_fips202/Makefile +++ b/examples/bring_your_own_fips202/Makefile @@ -19,7 +19,6 @@ INC= INC+=-Imlkem_native/mlkem INC+=-Imlkem_native/mlkem INC+=-Imlkem_native/mlkem/native -INC+=-Imlkem_native/mlkem/sys # Part B: # diff --git a/examples/bring_your_own_fips202/custom_fips202/fips202.h b/examples/bring_your_own_fips202/custom_fips202/fips202.h index 5ffe60fae..4bebebeb0 100644 --- a/examples/bring_your_own_fips202/custom_fips202/fips202.h +++ b/examples/bring_your_own_fips202/custom_fips202/fips202.h @@ -11,7 +11,7 @@ #ifndef FIPS202_H #define FIPS202_H -#include "namespace.h" +#include "common.h" #include "tiny_sha3/sha3.h" #define SHAKE128_RATE 168 diff --git a/examples/bring_your_own_fips202/custom_fips202/namespace.h b/examples/bring_your_own_fips202/custom_fips202/namespace.h deleted file mode 100644 index fab249afa..000000000 --- a/examples/bring_your_own_fips202/custom_fips202/namespace.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2024 The mlkem-native project authors - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef NAMESPACE_H -#define NAMESPACE_H - -#include "config.h" - -#if defined(MLKEM_USE_NATIVE_X86_64) -#define MLKEM_NATIVE_BACKEND X86_64 -#elif defined(MLKEM_USE_NATIVE_AARCH64) -#define MLKEM_NATIVE_BACKEND AARCH64 -#else -#define MLKEM_NATIVE_BACKEND C -#endif - -#define ___FIPS202_NAMESPACE(x1, x2, x3) x1##_##x2##_##x3 -#define __FIPS202_NAMESPACE(x1, x2, x3) ___FIPS202_NAMESPACE(x1, x2, x3) - -/* - * NAMESPACE is PQCP_MLKEM_NATIVE_FIPS202__ - * e.g., PQCP_MLKEM_NATIVE_FIPS202_AARCH64_ - */ -#define FIPS202_NAMESPACE(s) \ - __FIPS202_NAMESPACE(PQCP_MLKEM_NATIVE_FIPS202, MLKEM_NATIVE_BACKEND, s) -#define _FIPS202_NAMESPACE(s) \ - __FIPS202_NAMESPACE(_PQCP_MLKEM_NATIVE_FIPS202, MLKEM_NATIVE_BACKEND, s) - -#endif diff --git a/examples/bring_your_own_fips202/custom_fips202/tiny_sha3/Makefile b/examples/bring_your_own_fips202/custom_fips202/tiny_sha3/Makefile deleted file mode 100644 index e855f986f..000000000 --- a/examples/bring_your_own_fips202/custom_fips202/tiny_sha3/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -# SPDX-License-Identifier: MIT - -# Makefile -# 19-Nov-11 Markku-Juhani O. Saarinen - -BINARY = sha3test -OBJS = sha3.o main.o -DIST = tiny_sha3 - -CC = gcc -CFLAGS = -Wall -O3 -LIBS = -LDFLAGS = -INCLUDES = - -$(BINARY): $(OBJS) - $(CC) $(LDFLAGS) -o $(BINARY) $(OBJS) $(LIBS) - -.c.o: - $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ - -clean: - rm -rf $(DIST)-*.txz $(OBJS) $(BINARY) *~ - -dist: clean - cd ..; \ - tar cfvJ $(DIST)/$(DIST)-`date -u "+%Y%m%d%H%M00"`.txz \ - $(DIST)/* diff --git a/examples/bring_your_own_fips202/custom_fips202/tiny_sha3/main.c b/examples/bring_your_own_fips202/custom_fips202/tiny_sha3/main.c deleted file mode 100644 index b5fbbab6c..000000000 --- a/examples/bring_your_own_fips202/custom_fips202/tiny_sha3/main.c +++ /dev/null @@ -1,196 +0,0 @@ -// SPDX-License-Identifier: MIT -// -// main.c -// 19-Nov-11 Markku-Juhani O. Saarinen - -#include -#include -#include -#include "sha3.h" - -// read a hex string, return byte length or -1 on error. - -static int test_hexdigit(char ch) -{ - if (ch >= '0' && ch <= '9') - return ch - '0'; - if (ch >= 'A' && ch <= 'F') - return ch - 'A' + 10; - if (ch >= 'a' && ch <= 'f') - return ch - 'a' + 10; - return -1; -} - -static int test_readhex(uint8_t *buf, const char *str, int maxbytes) -{ - int i, h, l; - - for (i = 0; i < maxbytes; i++) - { - h = test_hexdigit(str[2 * i]); - if (h < 0) - return i; - l = test_hexdigit(str[2 * i + 1]); - if (l < 0) - return i; - buf[i] = (h << 4) + l; - } - - return i; -} - -// returns zero on success, nonzero + stderr messages on failure - -int test_sha3() -{ - // message / digest pairs, lifted from ShortMsgKAT_SHA3-xxx.txt files - // in the official package: https://github.com/gvanas/KeccakCodePackage - - const char *testvec[][2] = { - {// SHA3-224, corner case with 0-length message - "", "6B4E03423667DBB73B6E15454F0EB1ABD4597F9A1B078E3F5B5A6BC7"}, - {// SHA3-256, short message - "9F2FCC7C90DE090D6B87CD7E9718C1EA6CB21118FC2D5DE9F97E5DB6AC1E9C10", - "2F1A5F7159E34EA19CDDC70EBF9B81F1A66DB40615D7EAD3CC1F1B954D82A3AF"}, - {// SHA3-384, exact block size - "E35780EB9799AD4C77535D4DDB683CF33EF367715327CF4C4A58ED9CBDCDD486" - "F669F80189D549A9364FA82A51A52654EC721BB3AAB95DCEB4A86A6AFA93826D" - "B923517E928F33E3FBA850D45660EF83B9876ACCAFA2A9987A254B137C6E140A" - "21691E1069413848", - "D1C0FA85C8D183BEFF99AD9D752B263E286B477F79F0710B0103170173978133" - "44B99DAF3BB7B1BC5E8D722BAC85943A"}, - {// SHA3-512, multiblock message - "3A3A819C48EFDE2AD914FBF00E18AB6BC4F14513AB27D0C178A188B61431E7F5" - "623CB66B23346775D386B50E982C493ADBBFC54B9A3CD383382336A1A0B2150A" - "15358F336D03AE18F666C7573D55C4FD181C29E6CCFDE63EA35F0ADF5885CFC0" - "A3D84A2B2E4DD24496DB789E663170CEF74798AA1BBCD4574EA0BBA40489D764" - "B2F83AADC66B148B4A0CD95246C127D5871C4F11418690A5DDF01246A0C80A43" - "C70088B6183639DCFDA4125BD113A8F49EE23ED306FAAC576C3FB0C1E256671D" - "817FC2534A52F5B439F72E424DE376F4C565CCA82307DD9EF76DA5B7C4EB7E08" - "5172E328807C02D011FFBF33785378D79DC266F6A5BE6BB0E4A92ECEEBAEB1", - "6E8B8BD195BDD560689AF2348BDC74AB7CD05ED8B9A57711E9BE71E9726FDA45" - "91FEE12205EDACAF82FFBBAF16DFF9E702A708862080166C2FF6BA379BC7FFC2"}}; - - int i, fails, msg_len, sha_len; - uint8_t sha[64], buf[64], msg[256]; - - fails = 0; - for (i = 0; i < 4; i++) - { - memset(sha, 0, sizeof(sha)); - memset(buf, 0, sizeof(buf)); - memset(msg, 0, sizeof(msg)); - - msg_len = test_readhex(msg, testvec[i][0], sizeof(msg)); - sha_len = test_readhex(sha, testvec[i][1], sizeof(sha)); - - sha3(msg, msg_len, buf, sha_len); - - if (memcmp(sha, buf, sha_len) != 0) - { - fprintf(stderr, "[%d] SHA3-%d, len %d test FAILED.\n", i, sha_len * 8, - msg_len); - fails++; - } - } - - return fails; -} - -// test for SHAKE128 and SHAKE256 - -int test_shake() -{ - // Test vectors have bytes 480..511 of XOF output for given inputs. - // From http://csrc.nist.gov/groups/ST/toolkit/examples.html#aHashing - - const char *testhex[4] = { - // SHAKE128, message of length 0 - "43E41B45A653F2A5C4492C1ADD544512DDA2529833462B71A41A45BE97290B6F", - // SHAKE256, message of length 0 - "AB0BAE316339894304E35877B0C28A9B1FD166C796B9CC258A064A8F57E27F2A", - // SHAKE128, 1600-bit test pattern - "44C9FB359FD56AC0A9A75A743CFF6862F17D7259AB075216C0699511643B6439", - // SHAKE256, 1600-bit test pattern - "6A1A9D7846436E4DCA5728B6F760EEF0CA92BF0BE5615E96959D767197A0BEEB"}; - - int i, j, fails; - sha3_ctx_t sha3; - uint8_t buf[32], ref[32]; - - fails = 0; - - for (i = 0; i < 4; i++) - { - if ((i & 1) == 0) - { // test each twice - shake128_init(&sha3); - } - else - { - shake256_init(&sha3); - } - - if (i >= 2) - { // 1600-bit test pattern - memset(buf, 0xA3, 20); - for (j = 0; j < 200; j += 20) - shake_update(&sha3, buf, 20); - } - - shake_xof(&sha3); // switch to extensible output - - for (j = 0; j < 512; j += 32) // output. discard bytes 0..479 - shake_out(&sha3, buf, 32); - - // compare to reference - test_readhex(ref, testhex[i], sizeof(ref)); - if (memcmp(buf, ref, 32) != 0) - { - fprintf(stderr, "[%d] SHAKE%d, len %d test FAILED.\n", i, - i & 1 ? 256 : 128, i >= 2 ? 1600 : 0); - fails++; - } - } - - return fails; -} - -// test speed of the comp - -void test_speed() -{ - int i; - uint64_t st[25], x, n; - clock_t bg, us; - - for (i = 0; i < 25; i++) - st[i] = i; - - bg = clock(); - n = 0; - do - { - for (i = 0; i < 100000; i++) - sha3_keccakf(st); - n += i; - us = clock() - bg; - } while (us < 3 * CLOCKS_PER_SEC); - - x = 0; - for (i = 0; i < 25; i++) - x += st[i]; - - printf("(%016lX) %.3f Keccak-p[1600,24] / Second.\n", (unsigned long)x, - (CLOCKS_PER_SEC * ((double)n)) / ((double)us)); -} - -// main -int main(int argc, char **argv) -{ - if (test_sha3() == 0 && test_shake() == 0) - printf("FIPS 202 / SHA3, SHAKE128, SHAKE256 Self-Tests OK!\n"); - test_speed(); - - return 0; -} diff --git a/examples/custom_backend/Makefile b/examples/custom_backend/Makefile new file mode 100644 index 000000000..b1dad8549 --- /dev/null +++ b/examples/custom_backend/Makefile @@ -0,0 +1,64 @@ +# (SPDX-License-Identifier: CC-BY-4.0) + +.PHONY: build run clean + +# Part A: +# +# mlkem-native source and header files +# +# If you are not concerned about minimizing for a specific backend, +# you can just include _all_ source files into your build. +MLKEM_NATIVE_SOURCE=$(wildcard \ + mlkem_native/**/*.c \ + mlkem_native/**/*.c \ + mlkem_native/**/**/*.c \ + mlkem_native/**/**/**/*.c \ + mlkem_native/**/**/**/**/*.c) + +INC= +INC+=-Imlkem_native/ +INC+=-Imlkem_native/mlkem +INC+=-Imlkem_native/mlkem/native +INC+=-Imlkem_native/fips202 +INC+=-Imlkem_native/fips202/native + +# Part B: +# +# Random number generator +# +# !!! WARNING !!! +# +# The randombytes() implementation used here is for TESTING ONLY. +# You MUST NOT use this implementation outside of testing. +# +# !!! WARNING !!! +RNG_SOURCE=$(wildcard test_only_rng/*.c) + +# Part C: +# +# Your application source code +APP_SOURCE=$(wildcard *.c) + +ALL_SOURCE=$(MLKEM_NATIVE_SOURCE) $(RNG_SOURCE) $(APP_SOURCE) + +BUILD_DIR=build +BIN=test_binary + +CFLAGS=-DMLKEM_NATIVE_CONFIG_FILE="\"custom_config.h\"" + +BINARY_NAME_FULL=$(BUILD_DIR)/$(BIN) + +$(BINARY_NAME_FULL): $(ALL_SOURCE) + echo "$@" + mkdir -p $(BUILD_DIR) + $(CC) $(CFLAGS) $(INC) $^ -o $@ + +all: run + +build: $(BINARY_NAME_FULL) + +run: $(BINARY_NAME_FULL) + ./$(BINARY_NAME_FULL) + +clean: + rm -rf $(BUILD_DIR) diff --git a/examples/custom_backend/README.md b/examples/custom_backend/README.md new file mode 100644 index 000000000..b4bfac358 --- /dev/null +++ b/examples/custom_backend/README.md @@ -0,0 +1,32 @@ +[//]: # (SPDX-License-Identifier: CC-BY-4.0) + +# Using a custom configuration and FIPS-202 backend + +This directory contains a minimal example for how to use mlkem-native as a code package, with a custom FIPS-202 +backend and a custom configuration. We use the [tiny_sha3](https://github.com/mjosaarinen/tiny_sha3/) by Markku-J. O. +Saarinen as an example. + +## Components + +An application using mlkem-native with a custom FIPS-202 backend and custom configuration needs the following: + +1. Arithmetic part of the mlkem-native source tree: [`mlkem/`](../../mlkem). In this example, we disable arithmetic + backends, hence it is safe to remove the entire `native` subfolder. +2. A secure pseudo random number generator, implementing [`randombytes.h`](../../mlkem/randombytes.h). **WARNING:** The + `randombytes()` implementation used here is for TESTING ONLY. You MUST NOT use this implementation outside of testing. +3. FIPS-202 part of the mlkem-native source tree, [`fips/`](../../fips202). If you only want to use your backend, + you can remove all existing backends; that's what this example does. +4. A custom FIPS-202 backend. In this example, the metadata file is + [custom.h](mlkem_native/fips202/native/custom/custom.h), the implementation shim is + [custom_impl.h](mlkem_native/fips202/native/custom/src/custom_impl.h), wrapping the + [sha3.c](mlkem_native/fips202/native/custom/src/sha3.c) and setting `MLKEM_USE_FIPS101_X1_NATIVE` to indicate that we + replace 1-fold Keccak-F1600. +5. Either modify the existing [config.h](mlkem_native/mlkem/config.h), or register a new config. In this example, we add + a new config [custom_config.h](mlkem_native/custom_config.h) and register it from the command line for + `-DMLKEM_NATIVE_CONFIG_FILE="custom_config.h"` -- no further changes to the build are needed. For the sake of + demonstration, we set a custom namespace. We set `MLKEM_NATIVE_FIPS202_BACKEND` to point to our custom FIPS-202 + backend, but leave `MLKEM_NATIVE_ARITH_BACKEND` undefined to indicate that we wish to use the C backend. + +## Usage + +Build this example with `make build`, run with `make run`. diff --git a/examples/custom_backend/main.c b/examples/custom_backend/main.c new file mode 100644 index 000000000..5dc1cc2a8 --- /dev/null +++ b/examples/custom_backend/main.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2024 The mlkem-native project authors + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include + +const uint8_t expected_key[] = {0xe9, 0x13, 0x77, 0x84, 0x0e, 0x6b, 0x66, 0x94, + 0xea, 0xa9, 0xf0, 0x1c, 0x97, 0xff, 0x68, 0x87, + 0x4e, 0x8b, 0x0c, 0x52, 0x0b, 0x00, 0xc2, 0xcd, + 0xe3, 0x7c, 0x4f, 0xc2, 0x39, 0x62, 0x6e, 0x70}; + +int main(void) +{ + uint8_t pk[CRYPTO_PUBLICKEYBYTES]; + uint8_t sk[CRYPTO_SECRETKEYBYTES]; + uint8_t ct[CRYPTO_CIPHERTEXTBYTES]; + uint8_t key_a[CRYPTO_BYTES]; + uint8_t key_b[CRYPTO_BYTES]; + + printf("Generating keypair ... "); + + /* Alice generates a public key */ + crypto_kem_keypair(pk, sk); + + printf("DONE\n"); + printf("Encaps... "); + + /* Bob derives a secret key and creates a response */ + crypto_kem_enc(ct, key_b, pk); + + printf("DONE\n"); + printf("Decaps... "); + + /* Alice uses Bobs response to get her shared key */ + crypto_kem_dec(key_a, ct, sk); + + printf("DONE\n"); + printf("Compare... "); + + if (memcmp(key_a, key_b, CRYPTO_BYTES)) + { + printf("ERROR: Mismatching keys\n"); + return 1; + } + + /* Check against hardcoded result to make sure that + * we integrated custom FIPS202 correctly */ + if (memcmp(key_a, expected_key, CRYPTO_BYTES) != 0) + { + printf("ERROR: Unexpected result\n"); + return 1; + } + + printf("OK\n"); + + printf("Shared secret: "); + { + int i; + for (i = 0; i < sizeof(key_a); i++) + printf("%02x", key_a[i]); + } + printf("\n"); + + return 0; +} diff --git a/examples/custom_backend/mlkem_native/custom_config.h b/examples/custom_backend/mlkem_native/custom_config.h new file mode 100644 index 000000000..ab40528f3 --- /dev/null +++ b/examples/custom_backend/mlkem_native/custom_config.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2024 The mlkem-native project authors + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef MLKEM_NATIVE_CONFIG_H +#define MLKEM_NATIVE_CONFIG_H + +/****************************************************************************** + * Name: MLKEM_K + * + * Description: Determines the security level for ML-KEM + * - MLKEM_K=2 corresponds to ML-KEM-512 + * - MLKEM_K=3 corresponds to ML-KEM-768 + * - MLKEM_K=4 corresponds to ML-KEM-1024 + * + * This can also be set using CFLAGS. + * + *****************************************************************************/ +#define MLKEM_K 3 /* We want MLKEM-768 */ + +/****************************************************************************** + * Name: MLKEM_NATIVE_CONFIG_FILE + * + * Description: If defined, this is a header that will be included instead + * of mlkem/config.h. + * + * When you need to build mlkem-native in multiple configurations, + * this can be a convenient alternative to configuration via + * CFLAGS. + * + *****************************************************************************/ +/* No need to set this -- we _are_ already in a custom config */ +/* #define MLKEM_NATIVE_CONFIG_FILE "config.h" */ + +/****************************************************************************** + * Name: MLKEM_NAMESPACE + * _MLKEM_NAMESPACE + * + * Description: The macros to use to namespace global symbols + * from mlkem/. + *****************************************************************************/ +#define __CONC(a, b) a##b +#define CONC(a, b) __CONC(a, b) + +#define MLKEM_NAMESPACE(sym) CONC(CUSTOM_TINY_SHA3_, sym) +#define _MLKEM_NAMESPACE(sym) CONC(_CUSTOM_TINY_SHA3_, sym) + +/****************************************************************************** + * Name: FIPS202_NAMESPACE + * _FIPS202_NAMESPACE + * + * Description: The macros to use to namespace global symbols + * from fips202/. + *****************************************************************************/ +#define FIPS202_NAMESPACE(sym) CONC(CUSTOM_TINY_SHA3_, sym) +#define _FIPS202_NAMESPACE(sym) CONC(_CUSTOM_TINY_SHA3_, sym) + +/****************************************************************************** + * Name: MLKEM_USE_NATIVE + * + * Description: Determines whether a native backend should + * be used, if available. + * + * This can also be set using CFLAGS. + * + *****************************************************************************/ +#define MLKEM_USE_NATIVE + +/****************************************************************************** + * Name: MLKEM_NATIVE_ARITH_BACKEND + * + * Description: The arithmetic backend to use. + * + * This must be the filename of an arithmetic + * backend. The backend is expected to define + * + * - MLKEM_NATIVE_ARITH_BACKEND_NAME + * + * The name of the backend as used in the default namespace. + * + * - MLKEM_NATIVE_ARITH_BACKEND_IMPL + * + * The filename of the implementation of the arithmetic backend. + * + * See the existing backends for more information. + * + *****************************************************************************/ +/* Let's pretend we don't want an arithmetic backend */ +/* #define MLKEM_NATIVE_ARITH_BACKEND "native/default.h" */ + +/****************************************************************************** + * Name: MLKEM_NATIVE_FIPS202_BACKEND + * + * Description: The FIPS-202 backend to use. + * + * This must be the filename of an FIPS-202 + * backend. The backend is expected to define + * + * - MLKEM_NATIVE_FIPS202_BACKEND_NAME + * + * The name of the backend as used in the default namespace. + * + * - MLKEM_NATIVE_FIPS202_BACKEND_IMPL + * + * The filename of the implementation of the FIPS-202 backend. + * + * See the existing backends for more information. + * + *****************************************************************************/ +#define MLKEM_NATIVE_FIPS202_BACKEND "fips202/native/custom/custom.h" + +#endif /* MLkEM_NATIVE_CONFIG_H */ diff --git a/examples/custom_backend/mlkem_native/fips202/LICENSE b/examples/custom_backend/mlkem_native/fips202/LICENSE new file mode 120000 index 000000000..bcebb16c1 --- /dev/null +++ b/examples/custom_backend/mlkem_native/fips202/LICENSE @@ -0,0 +1 @@ +../../../../fips202/LICENSE \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/fips202/fips202.c b/examples/custom_backend/mlkem_native/fips202/fips202.c new file mode 120000 index 000000000..34cf3813b --- /dev/null +++ b/examples/custom_backend/mlkem_native/fips202/fips202.c @@ -0,0 +1 @@ +../../../../fips202/fips202.c \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/fips202/fips202.h b/examples/custom_backend/mlkem_native/fips202/fips202.h new file mode 120000 index 000000000..164a3b7b8 --- /dev/null +++ b/examples/custom_backend/mlkem_native/fips202/fips202.h @@ -0,0 +1 @@ +../../../../fips202/fips202.h \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/fips202/fips202_backend.h b/examples/custom_backend/mlkem_native/fips202/fips202_backend.h new file mode 120000 index 000000000..5397725dc --- /dev/null +++ b/examples/custom_backend/mlkem_native/fips202/fips202_backend.h @@ -0,0 +1 @@ +../../../../fips202/fips202_backend.h \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/fips202/fips202x4.c b/examples/custom_backend/mlkem_native/fips202/fips202x4.c new file mode 120000 index 000000000..fd9ec60d1 --- /dev/null +++ b/examples/custom_backend/mlkem_native/fips202/fips202x4.c @@ -0,0 +1 @@ +../../../../fips202/fips202x4.c \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/fips202/fips202x4.h b/examples/custom_backend/mlkem_native/fips202/fips202x4.h new file mode 120000 index 000000000..4dc5c3b80 --- /dev/null +++ b/examples/custom_backend/mlkem_native/fips202/fips202x4.h @@ -0,0 +1 @@ +../../../../fips202/fips202x4.h \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/fips202/keccakf1600.c b/examples/custom_backend/mlkem_native/fips202/keccakf1600.c new file mode 120000 index 000000000..53a5e8617 --- /dev/null +++ b/examples/custom_backend/mlkem_native/fips202/keccakf1600.c @@ -0,0 +1 @@ +../../../../fips202/keccakf1600.c \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/fips202/keccakf1600.h b/examples/custom_backend/mlkem_native/fips202/keccakf1600.h new file mode 120000 index 000000000..fe6e51a4c --- /dev/null +++ b/examples/custom_backend/mlkem_native/fips202/keccakf1600.h @@ -0,0 +1 @@ +../../../../fips202/keccakf1600.h \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/fips202/native/api.h b/examples/custom_backend/mlkem_native/fips202/native/api.h new file mode 120000 index 000000000..b255ddf09 --- /dev/null +++ b/examples/custom_backend/mlkem_native/fips202/native/api.h @@ -0,0 +1 @@ +../../../../../fips202/native/api.h \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/fips202/native/custom/custom.h b/examples/custom_backend/mlkem_native/fips202/native/custom/custom.h new file mode 100644 index 000000000..2ef194461 --- /dev/null +++ b/examples/custom_backend/mlkem_native/fips202/native/custom/custom.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024 The mlkem-native project authors + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Default FIPS202 assembly profile for AArch64 systems */ + +#ifdef FIPS202_NATIVE_PROFILE_H +#error Only one FIPS202 assembly profile can be defined -- did you include multiple profiles? +#else +#define FIPS202_NATIVE_PROFILE_H + +/* Identifier for this backend so that source and assembly files + * in the build can be appropriately guarded. */ +#define MLKEM_NATIVE_FIPS202_BACKEND_CUSTOM_TINY_SHA3 + +#define MLKEM_NATIVE_FIPS202_BACKEND_NAME TINY_SHA3 + +/* Filename of the C backend implementation. + * This is not inlined here because this header is included in assembly + * files as well. */ +#define MLKEM_NATIVE_FIPS202_BACKEND_IMPL \ + "fips202/native/custom/src/custom_impl.h" + +#endif /* FIPS202_NATIVE_PROFILE_H */ diff --git a/examples/custom_backend/mlkem_native/fips202/native/custom/src/LICENSE b/examples/custom_backend/mlkem_native/fips202/native/custom/src/LICENSE new file mode 100644 index 000000000..35741e52a --- /dev/null +++ b/examples/custom_backend/mlkem_native/fips202/native/custom/src/LICENSE @@ -0,0 +1,23 @@ +[//]: # (SPDX-License-Identifier: CC-BY-4.0) + +The MIT License (MIT) + +Copyright (c) 2015 Markku-Juhani O. Saarinen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/examples/custom_backend/mlkem_native/fips202/native/custom/src/README.md b/examples/custom_backend/mlkem_native/fips202/native/custom/src/README.md new file mode 100644 index 000000000..66684bec2 --- /dev/null +++ b/examples/custom_backend/mlkem_native/fips202/native/custom/src/README.md @@ -0,0 +1,63 @@ +[//]: # (SPDX-License-Identifier: MIT) + +# tiny_sha3 +Very small, readable implementation of the FIPS 202 and SHA3 hash function. +Public domain. + +### Updated 27-Dec-15: + +Added SHAKE128 and SHAKE256 code and test vectors. The code can actually do +a XOF of arbitrary size (like "SHAKE512"). + + +### Updated 03-Sep-15: + +Made the implementation portable. The API is now pretty much the +same that OpenSSL uses. + + +### Updated 07-Aug-15: + +Now that SHA3 spec is out, I've updated the package to match with the +new padding rules. There is literally one line difference between +Keccak 3.0 and SHA-3 implementations: + +``` + temp[inlen++] = 0x06; // XXX Padding Changed from Keccak 3.0 +``` + +The 0x06 constant there used to be 0x01. But this of course totally +breaks compatibility and test vectors had to be revised. + +SHA-3 Spec: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf + +Cheers, +- markku + + +### Original README.TXT from 19-Nov-11: + +Hi. + +The SHA-3 competition is nearing it's end and I would personally like +to support Keccak as the winner. I have a PhD in hash function cryptanalysis +so don't take my word for it, go ahead and look into the code ! + +Since I couldn't find a *compact* and/or *readable* implementation of Keccak +anywhere, here's one I cooked up as a service to the curious. + +This implementation is intended for study of the algorithm, not for +production use. + +The code works correctly on 64-bit little-endian platforms with gcc. +Like your Linux box. The main.c module contains self-tests for all +officially supported hash sizes. + +If you're looking for production code, the official multi-megabyte package +covers everyting you could possibly need and too much much more: +http://keccak.noekeon.org/ + +Cheers, +- Markku 19-Nov-11 + +Dr. Markku-Juhani O. Saarinen diff --git a/examples/custom_backend/mlkem_native/fips202/native/custom/src/custom_impl.h b/examples/custom_backend/mlkem_native/fips202/native/custom/src/custom_impl.h new file mode 100644 index 000000000..242d6b7f4 --- /dev/null +++ b/examples/custom_backend/mlkem_native/fips202/native/custom/src/custom_impl.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2024 The mlkem-native project authors + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Default FIPS202 assembly profile for AArch64 systems */ + +#ifdef FIPS202_NATIVE_PROFILE_IMPL_H +#error Only one FIPS202 assembly profile can be defined -- did you include multiple profiles? +#else +#define FIPS202_NATIVE_PROFILE_IMPL_H + +#include "sha3.h" + +/* Replace (single) Keccak-F1600 by tiny-SHA3's */ +#define MLKEM_USE_FIPS202_X1_NATIVE +static INLINE void keccak_f1600_x1_native(uint64_t *state) +{ + sha3_keccakf(state); +} + +#endif /* FIPS202_NATIVE_PROFILE_H */ diff --git a/examples/custom_backend/mlkem_native/fips202/native/custom/src/sha3.c b/examples/custom_backend/mlkem_native/fips202/native/custom/src/sha3.c new file mode 100644 index 000000000..c21684ae5 --- /dev/null +++ b/examples/custom_backend/mlkem_native/fips202/native/custom/src/sha3.c @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: MIT +// +// sha3.c +// 19-Nov-11 Markku-Juhani O. Saarinen + +// Revised 07-Aug-15 to match with official release of FIPS PUB 202 "SHA3" +// Revised 03-Sep-15 for portability + OpenSSL - style API + +#include "sha3.h" + +// update the state with given number of rounds + +void sha3_keccakf(uint64_t st[25]) +{ + // constants + const uint64_t keccakf_rndc[24] = { + 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, + 0x8000000080008000, 0x000000000000808b, 0x0000000080000001, + 0x8000000080008081, 0x8000000000008009, 0x000000000000008a, + 0x0000000000000088, 0x0000000080008009, 0x000000008000000a, + 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, + 0x8000000000008003, 0x8000000000008002, 0x8000000000000080, + 0x000000000000800a, 0x800000008000000a, 0x8000000080008081, + 0x8000000000008080, 0x0000000080000001, 0x8000000080008008}; + const int keccakf_rotc[24] = {1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, + 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44}; + const int keccakf_piln[24] = {10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, + 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1}; + + // variables + int i, j, r; + uint64_t t, bc[5]; + +#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ + uint8_t *v; + + // endianess conversion. this is redundant on little-endian targets + for (i = 0; i < 25; i++) + { + v = (uint8_t *)&st[i]; + st[i] = ((uint64_t)v[0]) | (((uint64_t)v[1]) << 8) | + (((uint64_t)v[2]) << 16) | (((uint64_t)v[3]) << 24) | + (((uint64_t)v[4]) << 32) | (((uint64_t)v[5]) << 40) | + (((uint64_t)v[6]) << 48) | (((uint64_t)v[7]) << 56); + } +#endif + + // actual iteration + for (r = 0; r < KECCAKF_ROUNDS; r++) + { + // Theta + for (i = 0; i < 5; i++) + bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15] ^ st[i + 20]; + + for (i = 0; i < 5; i++) + { + t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1); + for (j = 0; j < 25; j += 5) + st[j + i] ^= t; + } + + // Rho Pi + t = st[1]; + for (i = 0; i < 24; i++) + { + j = keccakf_piln[i]; + bc[0] = st[j]; + st[j] = ROTL64(t, keccakf_rotc[i]); + t = bc[0]; + } + + // Chi + for (j = 0; j < 25; j += 5) + { + for (i = 0; i < 5; i++) + bc[i] = st[j + i]; + for (i = 0; i < 5; i++) + st[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5]; + } + + // Iota + st[0] ^= keccakf_rndc[r]; + } + +#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ + // endianess conversion. this is redundant on little-endian targets + for (i = 0; i < 25; i++) + { + v = (uint8_t *)&st[i]; + t = st[i]; + v[0] = t & 0xFF; + v[1] = (t >> 8) & 0xFF; + v[2] = (t >> 16) & 0xFF; + v[3] = (t >> 24) & 0xFF; + v[4] = (t >> 32) & 0xFF; + v[5] = (t >> 40) & 0xFF; + v[6] = (t >> 48) & 0xFF; + v[7] = (t >> 56) & 0xFF; + } +#endif +} + +// Initialize the context for SHA3 + +int sha3_init(sha3_ctx_t *c, int mdlen) +{ + int i; + + for (i = 0; i < 25; i++) + c->st.q[i] = 0; + c->mdlen = mdlen; + c->rsiz = 200 - 2 * mdlen; + c->pt = 0; + + return 1; +} + +// update state with more data + +int sha3_update(sha3_ctx_t *c, const void *data, size_t len) +{ + size_t i; + int j; + + j = c->pt; + for (i = 0; i < len; i++) + { + c->st.b[j++] ^= ((const uint8_t *)data)[i]; + if (j >= c->rsiz) + { + sha3_keccakf(c->st.q); + j = 0; + } + } + c->pt = j; + + return 1; +} + +// finalize and output a hash + +int sha3_final(void *md, sha3_ctx_t *c) +{ + int i; + + c->st.b[c->pt] ^= 0x06; + c->st.b[c->rsiz - 1] ^= 0x80; + sha3_keccakf(c->st.q); + + for (i = 0; i < c->mdlen; i++) + { + ((uint8_t *)md)[i] = c->st.b[i]; + } + + return 1; +} + +// compute a SHA-3 hash (md) of given byte length from "in" + +void *sha3(const void *in, size_t inlen, void *md, int mdlen) +{ + sha3_ctx_t sha3; + + sha3_init(&sha3, mdlen); + sha3_update(&sha3, in, inlen); + sha3_final(md, &sha3); + + return md; +} + +// SHAKE128 and SHAKE256 extensible-output functionality + +void shake_xof(sha3_ctx_t *c) +{ + c->st.b[c->pt] ^= 0x1F; + c->st.b[c->rsiz - 1] ^= 0x80; + sha3_keccakf(c->st.q); + c->pt = 0; +} + +void shake_out(sha3_ctx_t *c, void *out, size_t len) +{ + size_t i; + int j; + + j = c->pt; + for (i = 0; i < len; i++) + { + if (j >= c->rsiz) + { + sha3_keccakf(c->st.q); + j = 0; + } + ((uint8_t *)out)[i] = c->st.b[j++]; + } + c->pt = j; +} diff --git a/examples/custom_backend/mlkem_native/fips202/native/custom/src/sha3.h b/examples/custom_backend/mlkem_native/fips202/native/custom/src/sha3.h new file mode 100644 index 000000000..fb5276059 --- /dev/null +++ b/examples/custom_backend/mlkem_native/fips202/native/custom/src/sha3.h @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: MIT +// +// sha3.h +// 19-Nov-11 Markku-Juhani O. Saarinen + +#ifndef SHA3_H +#define SHA3_H + +#include +#include + +#ifndef KECCAKF_ROUNDS +#define KECCAKF_ROUNDS 24 +#endif + +#ifndef ROTL64 +#define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y)))) +#endif + +// state context +typedef struct +{ + union + { // state: + uint8_t b[200]; // 8-bit bytes + uint64_t q[25]; // 64-bit words + } st; + int pt, rsiz, mdlen; // these don't overflow +} sha3_ctx_t; + +// Compression function. +void sha3_keccakf(uint64_t st[25]); + +// OpenSSL - like interfece +int sha3_init(sha3_ctx_t *c, int mdlen); // mdlen = hash output in bytes +int sha3_update(sha3_ctx_t *c, const void *data, size_t len); +int sha3_final(void *md, sha3_ctx_t *c); // digest goes to md + +// compute a sha3 hash (md) of given byte length from "in" +void *sha3(const void *in, size_t inlen, void *md, int mdlen); + +// SHAKE128 and SHAKE256 extensible-output functions +#define shake128_init(c) sha3_init(c, 16) +#define shake256_init(c) sha3_init(c, 32) +#define shake_update sha3_update + +void shake_xof(sha3_ctx_t *c); +void shake_out(sha3_ctx_t *c, void *out, size_t len); + +#endif diff --git a/examples/custom_backend/mlkem_native/mlkem/LICENSE b/examples/custom_backend/mlkem_native/mlkem/LICENSE new file mode 120000 index 000000000..8fae44d93 --- /dev/null +++ b/examples/custom_backend/mlkem_native/mlkem/LICENSE @@ -0,0 +1 @@ +../../../../mlkem/LICENSE \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/mlkem/arith_backend.h b/examples/custom_backend/mlkem_native/mlkem/arith_backend.h new file mode 120000 index 000000000..c7abf8ecd --- /dev/null +++ b/examples/custom_backend/mlkem_native/mlkem/arith_backend.h @@ -0,0 +1 @@ +../../../../mlkem/arith_backend.h \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/mlkem/cbd.c b/examples/custom_backend/mlkem_native/mlkem/cbd.c new file mode 120000 index 000000000..66131480c --- /dev/null +++ b/examples/custom_backend/mlkem_native/mlkem/cbd.c @@ -0,0 +1 @@ +../../../../mlkem/cbd.c \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/mlkem/cbd.h b/examples/custom_backend/mlkem_native/mlkem/cbd.h new file mode 120000 index 000000000..941b8bd44 --- /dev/null +++ b/examples/custom_backend/mlkem_native/mlkem/cbd.h @@ -0,0 +1 @@ +../../../../mlkem/cbd.h \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/mlkem/cbmc.h b/examples/custom_backend/mlkem_native/mlkem/cbmc.h new file mode 120000 index 000000000..1d7ad6bf2 --- /dev/null +++ b/examples/custom_backend/mlkem_native/mlkem/cbmc.h @@ -0,0 +1 @@ +../../../../mlkem/cbmc.h \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/mlkem/common.h b/examples/custom_backend/mlkem_native/mlkem/common.h new file mode 120000 index 000000000..f6ec75f66 --- /dev/null +++ b/examples/custom_backend/mlkem_native/mlkem/common.h @@ -0,0 +1 @@ +../../../../mlkem/common.h \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/mlkem/config.h b/examples/custom_backend/mlkem_native/mlkem/config.h new file mode 120000 index 000000000..a71bed830 --- /dev/null +++ b/examples/custom_backend/mlkem_native/mlkem/config.h @@ -0,0 +1 @@ +../../../../mlkem/config.h \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/mlkem/debug b/examples/custom_backend/mlkem_native/mlkem/debug new file mode 120000 index 000000000..cd511d740 --- /dev/null +++ b/examples/custom_backend/mlkem_native/mlkem/debug @@ -0,0 +1 @@ +../../../../mlkem/debug \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/mlkem/indcpa.c b/examples/custom_backend/mlkem_native/mlkem/indcpa.c new file mode 120000 index 000000000..56b7fc666 --- /dev/null +++ b/examples/custom_backend/mlkem_native/mlkem/indcpa.c @@ -0,0 +1 @@ +../../../../mlkem/indcpa.c \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/mlkem/indcpa.h b/examples/custom_backend/mlkem_native/mlkem/indcpa.h new file mode 120000 index 000000000..6bec2894b --- /dev/null +++ b/examples/custom_backend/mlkem_native/mlkem/indcpa.h @@ -0,0 +1 @@ +../../../../mlkem/indcpa.h \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/mlkem/kem.c b/examples/custom_backend/mlkem_native/mlkem/kem.c new file mode 120000 index 000000000..2677344d2 --- /dev/null +++ b/examples/custom_backend/mlkem_native/mlkem/kem.c @@ -0,0 +1 @@ +../../../../mlkem/kem.c \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/mlkem/kem.h b/examples/custom_backend/mlkem_native/mlkem/kem.h new file mode 120000 index 000000000..6f74e1af6 --- /dev/null +++ b/examples/custom_backend/mlkem_native/mlkem/kem.h @@ -0,0 +1 @@ +../../../../mlkem/kem.h \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/mlkem/namespace.h b/examples/custom_backend/mlkem_native/mlkem/namespace.h new file mode 120000 index 000000000..c41101c01 --- /dev/null +++ b/examples/custom_backend/mlkem_native/mlkem/namespace.h @@ -0,0 +1 @@ +../../../../mlkem/namespace.h \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/mlkem/ntt.c b/examples/custom_backend/mlkem_native/mlkem/ntt.c new file mode 120000 index 000000000..693bc94f2 --- /dev/null +++ b/examples/custom_backend/mlkem_native/mlkem/ntt.c @@ -0,0 +1 @@ +../../../../mlkem/ntt.c \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/mlkem/ntt.h b/examples/custom_backend/mlkem_native/mlkem/ntt.h new file mode 120000 index 000000000..5ea1982c5 --- /dev/null +++ b/examples/custom_backend/mlkem_native/mlkem/ntt.h @@ -0,0 +1 @@ +../../../../mlkem/ntt.h \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/mlkem/params.h b/examples/custom_backend/mlkem_native/mlkem/params.h new file mode 120000 index 000000000..f9fc45bfb --- /dev/null +++ b/examples/custom_backend/mlkem_native/mlkem/params.h @@ -0,0 +1 @@ +../../../../mlkem/params.h \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/mlkem/poly.c b/examples/custom_backend/mlkem_native/mlkem/poly.c new file mode 120000 index 000000000..8f37481c9 --- /dev/null +++ b/examples/custom_backend/mlkem_native/mlkem/poly.c @@ -0,0 +1 @@ +../../../../mlkem/poly.c \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/mlkem/poly.h b/examples/custom_backend/mlkem_native/mlkem/poly.h new file mode 120000 index 000000000..6aa17ed35 --- /dev/null +++ b/examples/custom_backend/mlkem_native/mlkem/poly.h @@ -0,0 +1 @@ +../../../../mlkem/poly.h \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/mlkem/polyvec.c b/examples/custom_backend/mlkem_native/mlkem/polyvec.c new file mode 120000 index 000000000..358c967ff --- /dev/null +++ b/examples/custom_backend/mlkem_native/mlkem/polyvec.c @@ -0,0 +1 @@ +../../../../mlkem/polyvec.c \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/mlkem/polyvec.h b/examples/custom_backend/mlkem_native/mlkem/polyvec.h new file mode 120000 index 000000000..b3a001d95 --- /dev/null +++ b/examples/custom_backend/mlkem_native/mlkem/polyvec.h @@ -0,0 +1 @@ +../../../../mlkem/polyvec.h \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/mlkem/randombytes.h b/examples/custom_backend/mlkem_native/mlkem/randombytes.h new file mode 120000 index 000000000..d1b4aeb9e --- /dev/null +++ b/examples/custom_backend/mlkem_native/mlkem/randombytes.h @@ -0,0 +1 @@ +../../../../mlkem/randombytes.h \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/mlkem/reduce.h b/examples/custom_backend/mlkem_native/mlkem/reduce.h new file mode 120000 index 000000000..6b2408820 --- /dev/null +++ b/examples/custom_backend/mlkem_native/mlkem/reduce.h @@ -0,0 +1 @@ +../../../../mlkem/reduce.h \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/mlkem/rej_uniform.c b/examples/custom_backend/mlkem_native/mlkem/rej_uniform.c new file mode 120000 index 000000000..bcc45b521 --- /dev/null +++ b/examples/custom_backend/mlkem_native/mlkem/rej_uniform.c @@ -0,0 +1 @@ +../../../../mlkem/rej_uniform.c \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/mlkem/rej_uniform.h b/examples/custom_backend/mlkem_native/mlkem/rej_uniform.h new file mode 120000 index 000000000..1d2f26cdb --- /dev/null +++ b/examples/custom_backend/mlkem_native/mlkem/rej_uniform.h @@ -0,0 +1 @@ +../../../../mlkem/rej_uniform.h \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/mlkem/symmetric.h b/examples/custom_backend/mlkem_native/mlkem/symmetric.h new file mode 120000 index 000000000..a44e26f71 --- /dev/null +++ b/examples/custom_backend/mlkem_native/mlkem/symmetric.h @@ -0,0 +1 @@ +../../../../mlkem/symmetric.h \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/mlkem/sys.h b/examples/custom_backend/mlkem_native/mlkem/sys.h new file mode 120000 index 000000000..c6b25c7f2 --- /dev/null +++ b/examples/custom_backend/mlkem_native/mlkem/sys.h @@ -0,0 +1 @@ +../../../../mlkem/sys.h \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/mlkem/verify.c b/examples/custom_backend/mlkem_native/mlkem/verify.c new file mode 120000 index 000000000..d49e9df42 --- /dev/null +++ b/examples/custom_backend/mlkem_native/mlkem/verify.c @@ -0,0 +1 @@ +../../../../mlkem/verify.c \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/mlkem/verify.h b/examples/custom_backend/mlkem_native/mlkem/verify.h new file mode 120000 index 000000000..82ae31329 --- /dev/null +++ b/examples/custom_backend/mlkem_native/mlkem/verify.h @@ -0,0 +1 @@ +../../../../mlkem/verify.h \ No newline at end of file diff --git a/examples/custom_backend/mlkem_native/mlkem/zetas.c b/examples/custom_backend/mlkem_native/mlkem/zetas.c new file mode 120000 index 000000000..4e1a91dda --- /dev/null +++ b/examples/custom_backend/mlkem_native/mlkem/zetas.c @@ -0,0 +1 @@ +../../../../mlkem/zetas.c \ No newline at end of file diff --git a/examples/custom_backend/test_only_rng/notrandombytes.c b/examples/custom_backend/test_only_rng/notrandombytes.c new file mode 100644 index 000000000..93807622d --- /dev/null +++ b/examples/custom_backend/test_only_rng/notrandombytes.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2024 The mlkem-native project authors + * SPDX-License-Identifier: LicenseRef-PD-hp OR CC0-1.0 OR 0BSD OR MIT-0 OR MI + * Based on https://cr.yp.to/papers.html#surf by Daniel. J. Bernstein + */ + +/** + * WARNING + * + * The randombytes() implementation in this file is for TESTING ONLY. + * You MUST NOT use this implementation outside of testing. + * + */ + +#warning !!! WARNING !!! +#warning THIS BUILD IS USING A TEST-ONLY RANDOM NUMBER GENERATOR WHICH MUST NOT BE USED IN PRODUCTION + +#include +#include "randombytes.h" + +static uint32_t seed[32] = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3, + 2, 3, 8, 4, 6, 2, 6, 4, 3, 3, 8, 3, 2, 7, 9, 5}; +static uint32_t in[12]; +static uint32_t out[8]; +static int32_t outleft = 0; + +#define ROTATE(x, b) (((x) << (b)) | ((x) >> (32 - (b)))) +#define MUSH(i, b) x = t[i] += (((x ^ seed[i]) + sum) ^ ROTATE(x, b)); + +static void surf(void) +{ + uint32_t t[12]; + uint32_t x; + uint32_t sum = 0; + int32_t r; + int32_t i; + int32_t loop; + + for (i = 0; i < 12; ++i) + { + t[i] = in[i] ^ seed[12 + i]; + } + for (i = 0; i < 8; ++i) + { + out[i] = seed[24 + i]; + } + x = t[11]; + for (loop = 0; loop < 2; ++loop) + { + for (r = 0; r < 16; ++r) + { + sum += 0x9e3779b9; + MUSH(0, 5) + MUSH(1, 7) + MUSH(2, 9) + MUSH(3, 13) + MUSH(4, 5) + MUSH(5, 7) + MUSH(6, 9) + MUSH(7, 13) + MUSH(8, 5) + MUSH(9, 7) + MUSH(10, 9) + MUSH(11, 13) + } + for (i = 0; i < 8; ++i) + { + out[i] ^= t[i + 4]; + } + } +} + +void randombytes(uint8_t *buf, size_t n) +{ + while (n > 0) + { + if (!outleft) + { + if (!++in[0]) + { + if (!++in[1]) + { + if (!++in[2]) + { + ++in[3]; + } + } + } + surf(); + outleft = 8; + } + *buf = (uint8_t)out[--outleft]; + ++buf; + --n; + } +} diff --git a/examples/mlkem_native_as_code_package/Makefile b/examples/mlkem_native_as_code_package/Makefile index 1a6aed46a..127afd7d2 100644 --- a/examples/mlkem_native_as_code_package/Makefile +++ b/examples/mlkem_native_as_code_package/Makefile @@ -21,7 +21,6 @@ INC+=-Imlkem_native/mlkem INC+=-Imlkem_native/mlkem/native INC+=-Imlkem_native/fips202 INC+=-Imlkem_native/fips202/native -INC+=-Imlkem_native/mlkem/sys # Part B: # diff --git a/fips202/fips202.h b/fips202/fips202.h index 48429c271..333a959d7 100644 --- a/fips202/fips202.h +++ b/fips202/fips202.h @@ -7,9 +7,8 @@ #include #include -#include "namespace.h" - #include "cbmc.h" +#include "common.h" #define SHAKE128_RATE 168 #define SHAKE256_RATE 136 diff --git a/fips202/fips202_backend.h b/fips202/fips202_backend.h new file mode 100644 index 000000000..24e6593b2 --- /dev/null +++ b/fips202/fips202_backend.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2024 The mlkem-native project authors + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifdef MLKEM_NATIVE_FIPS202_IMPL_H +#error Only one FIPS202 assembly profile can be defined -- did you include multiple profiles? +#else +#define MLKEM_NATIVE_FIPS202_IMPL_H + +/* Include to enforce consistency of API and implementation */ +#include "native/api.h" + +#if defined(MLKEM_NATIVE_FIPS202_BACKEND_IMPL) +#include MLKEM_NATIVE_FIPS202_BACKEND_IMPL +#endif + +#endif /* MLKEM_NATIVE_FIPS202_IMPL_H */ diff --git a/fips202/fips202x4.h b/fips202/fips202x4.h index 33a732a88..1bb0d08c7 100644 --- a/fips202/fips202x4.h +++ b/fips202/fips202x4.h @@ -7,9 +7,9 @@ #include #include +#include "common.h" #include "fips202.h" #include "keccakf1600.h" -#include "namespace.h" #include "cbmc.h" diff --git a/fips202/keccakf1600.c b/fips202/keccakf1600.c index 7b653fca9..5049999dd 100644 --- a/fips202/keccakf1600.c +++ b/fips202/keccakf1600.c @@ -15,7 +15,7 @@ #include #include "config.h" -#include "fips202_native.h" +#include "fips202_backend.h" #include "cbmc.h" diff --git a/fips202/keccakf1600.h b/fips202/keccakf1600.h index 7341df0bf..3d59e0b19 100644 --- a/fips202/keccakf1600.h +++ b/fips202/keccakf1600.h @@ -6,10 +6,8 @@ #define KECCAKF1600_H #include -#include "fips202_native.h" -#include "namespace.h" - #include "cbmc.h" +#include "common.h" #define KECCAK_LANES 25 /* diff --git a/fips202/namespace.h b/fips202/namespace.h deleted file mode 100644 index fab249afa..000000000 --- a/fips202/namespace.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2024 The mlkem-native project authors - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef NAMESPACE_H -#define NAMESPACE_H - -#include "config.h" - -#if defined(MLKEM_USE_NATIVE_X86_64) -#define MLKEM_NATIVE_BACKEND X86_64 -#elif defined(MLKEM_USE_NATIVE_AARCH64) -#define MLKEM_NATIVE_BACKEND AARCH64 -#else -#define MLKEM_NATIVE_BACKEND C -#endif - -#define ___FIPS202_NAMESPACE(x1, x2, x3) x1##_##x2##_##x3 -#define __FIPS202_NAMESPACE(x1, x2, x3) ___FIPS202_NAMESPACE(x1, x2, x3) - -/* - * NAMESPACE is PQCP_MLKEM_NATIVE_FIPS202__ - * e.g., PQCP_MLKEM_NATIVE_FIPS202_AARCH64_ - */ -#define FIPS202_NAMESPACE(s) \ - __FIPS202_NAMESPACE(PQCP_MLKEM_NATIVE_FIPS202, MLKEM_NATIVE_BACKEND, s) -#define _FIPS202_NAMESPACE(s) \ - __FIPS202_NAMESPACE(_PQCP_MLKEM_NATIVE_FIPS202, MLKEM_NATIVE_BACKEND, s) - -#endif diff --git a/fips202/native/aarch64/cortex_a55.h b/fips202/native/aarch64/cortex_a55.h new file mode 100644 index 000000000..3d9d92879 --- /dev/null +++ b/fips202/native/aarch64/cortex_a55.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024 The mlkem-native project authors + * SPDX-License-Identifier: Apache-2.0 + */ + +/* FIPS202 assembly profile targeting Cortex-A55 */ + +#ifdef FIPS202_NATIVE_PROFILE_H +#error Only one FIPS202 assembly profile can be defined -- did you include multiple profiles? +#else +#define FIPS202_NATIVE_PROFILE_H + +/* Identifier for this backend so that source and assembly files + * in the build can be appropriately guarded. */ +#define MLKEM_NATIVE_FIPS202_BACKEND_AARCH64_A55 + +#define MLKEM_NATIVE_FIPS202_BACKEND_NAME AARCH64_A55 + +/* Filename of the C backend implementation. + * This is not inlined here because this header is included in assembly + * files as well. */ +#define MLKEM_NATIVE_FIPS202_BACKEND_IMPL "aarch64/src/cortex_a55_impl.h" + +#endif /* FIPS202_NATIVE_PROFILE_H */ diff --git a/fips202/native/aarch64/default.h b/fips202/native/aarch64/default.h new file mode 100644 index 000000000..1386c6440 --- /dev/null +++ b/fips202/native/aarch64/default.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024 The mlkem-native project authors + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Default FIPS202 assembly profile for AArch64 systems */ + +#ifdef FIPS202_NATIVE_PROFILE_H +#error Only one FIPS202 assembly profile can be defined -- did you include multiple profiles? +#else +#define FIPS202_NATIVE_PROFILE_H + +/* Identifier for this backend so that source and assembly files + * in the build can be appropriately guarded. */ +#define MLKEM_NATIVE_FIPS202_BACKEND_AARCH64_DEFAULT + +#define MLKEM_NATIVE_FIPS202_BACKEND_NAME AARCH64_DEFAULT + +/* Filename of the C backend implementation. + * This is not inlined here because this header is included in assembly + * files as well. */ +#define MLKEM_NATIVE_FIPS202_BACKEND_IMPL "aarch64/src/default_impl.h" + +#endif /* FIPS202_NATIVE_PROFILE_H */ diff --git a/fips202/native/aarch64/common.i b/fips202/native/aarch64/src/common.i similarity index 100% rename from fips202/native/aarch64/common.i rename to fips202/native/aarch64/src/common.i diff --git a/fips202/native/aarch64/profiles/cortex_a55.h b/fips202/native/aarch64/src/cortex_a55_impl.h similarity index 76% rename from fips202/native/aarch64/profiles/cortex_a55.h rename to fips202/native/aarch64/src/cortex_a55_impl.h index 3ca536bf4..90b857f66 100644 --- a/fips202/native/aarch64/profiles/cortex_a55.h +++ b/fips202/native/aarch64/src/cortex_a55_impl.h @@ -5,12 +5,12 @@ /* FIPS202 assembly profile targeting Cortex-A55 */ -#ifdef FIPS202_NATIVE_PROFILE_H +#ifdef FIPS202_NATIVE_PROFILE_IMPL_H #error Only one FIPS202 assembly profile can be defined -- did you include multiple profiles? #else -#define FIPS202_NATIVE_PROFILE_H +#define FIPS202_NATIVE_PROFILE_IMPL_H -#include "../fips202_native_aarch64.h" +#include "fips202_native_aarch64.h" /* * On Cortex-A55, we use lazy rotation assembly for Keccak-x1, @@ -22,4 +22,4 @@ static INLINE void keccak_f1600_x1_native(uint64_t *state) keccak_f1600_x1_scalar_asm_opt(state); } -#endif /* FIPS202_NATIVE_PROFILE_H */ +#endif /* FIPS202_NATIVE_PROFILE_IMPL_H */ diff --git a/fips202/native/aarch64/profiles/default.h b/fips202/native/aarch64/src/default_impl.h similarity index 95% rename from fips202/native/aarch64/profiles/default.h rename to fips202/native/aarch64/src/default_impl.h index 3a9da28b7..4d28e35bf 100644 --- a/fips202/native/aarch64/profiles/default.h +++ b/fips202/native/aarch64/src/default_impl.h @@ -5,12 +5,12 @@ /* Default FIPS202 assembly profile for AArch64 systems */ -#ifdef FIPS202_NATIVE_PROFILE_H +#ifdef FIPS202_NATIVE_PROFILE_IMPL_H #error Only one FIPS202 assembly profile can be defined -- did you include multiple profiles? #else -#define FIPS202_NATIVE_PROFILE_H +#define FIPS202_NATIVE_PROFILE_IMPL_H -#include "../fips202_native_aarch64.h" +#include "fips202_native_aarch64.h" /* * Default logic to decide which implementation to use. diff --git a/fips202/native/aarch64/fips202_native_aarch64.h b/fips202/native/aarch64/src/fips202_native_aarch64.h similarity index 91% rename from fips202/native/aarch64/fips202_native_aarch64.h rename to fips202/native/aarch64/src/fips202_native_aarch64.h index 72e7c9710..d62b2c958 100644 --- a/fips202/native/aarch64/fips202_native_aarch64.h +++ b/fips202/native/aarch64/src/fips202_native_aarch64.h @@ -6,11 +6,8 @@ #define FIPS202_AARCH64_NATIVE_H #include -#include "config.h" -#include "namespace.h" -#include "params.h" +#include "common.h" -#ifdef MLKEM_USE_NATIVE_AARCH64 #define keccak_f1600_x1_scalar_asm_opt \ FIPS202_NAMESPACE(keccak_f1600_x1_scalar_asm_opt) void keccak_f1600_x1_scalar_asm_opt(uint64_t *state); @@ -38,6 +35,5 @@ void keccak_f1600_x4_scalar_v84a_asm_hybrid_opt(uint64_t *state); #define keccak_f1600_x4_scalar_v8a_v84a_hybrid_asm_opt \ FIPS202_NAMESPACE(keccak_f1600_x4_scalar_v8a_v84a_hybrid_asm_opt) void keccak_f1600_x4_scalar_v8a_v84a_hybrid_asm_opt(uint64_t *state); -#endif /* MLKEM_USE_NATIVE_AARCH64 */ #endif /* FIPS202_AARCH64_NATIVE_H */ diff --git a/fips202/native/aarch64/keccak_f1600_x1_scalar_asm_opt.S b/fips202/native/aarch64/src/keccak_f1600_x1_scalar_asm_opt.S similarity index 99% rename from fips202/native/aarch64/keccak_f1600_x1_scalar_asm_opt.S rename to fips202/native/aarch64/src/keccak_f1600_x1_scalar_asm_opt.S index 3db9e2046..3655a219d 100644 --- a/fips202/native/aarch64/keccak_f1600_x1_scalar_asm_opt.S +++ b/fips202/native/aarch64/src/keccak_f1600_x1_scalar_asm_opt.S @@ -28,12 +28,12 @@ // Author: Hanno Becker // Author: Matthias Kannwischer -#include "config.h" -#if defined(MLKEM_USE_NATIVE_AARCH64) +#include "common.h" +#if defined(MLKEM_NATIVE_FIPS202_BACKEND_AARCH64_DEFAULT) || \ + defined(MLKEM_NATIVE_FIPS202_BACKEND_AARCH64_A55) // Needed to provide ASM_LOAD directive #include "common.i" -#include "namespace.h" /********************** CONSTANTS *************************/ .data @@ -457,4 +457,5 @@ initial: free_stack ret -#endif /* MLKEM_USE_NATIVE_AARCH64 */ +#endif /* defined(MLKEM_NATIVE_FIPS202_BACKEND_AARCH64_DEFAULT) || + defined(MLKEM_NATIVE_FIPS202_BACKEND_AARCH64_A55) */ diff --git a/fips202/native/aarch64/keccak_f1600_x1_v84a_asm_clean.S b/fips202/native/aarch64/src/keccak_f1600_x1_v84a_asm_clean.S similarity index 98% rename from fips202/native/aarch64/keccak_f1600_x1_v84a_asm_clean.S rename to fips202/native/aarch64/src/keccak_f1600_x1_v84a_asm_clean.S index 0613a8a75..c60e4cad4 100644 --- a/fips202/native/aarch64/keccak_f1600_x1_v84a_asm_clean.S +++ b/fips202/native/aarch64/src/keccak_f1600_x1_v84a_asm_clean.S @@ -37,8 +37,9 @@ // during load and store, so that the caller need not do this. // -#include "config.h" -#if defined(MLKEM_USE_NATIVE_AARCH64) +#include "common.h" +#if defined(MLKEM_NATIVE_FIPS202_BACKEND_AARCH64_DEFAULT) || \ + defined(MLKEM_NATIVE_FIPS202_BACKEND_AARCH64_A55) // Needed to provide ASM_LOAD directive #include "common.i" diff --git a/fips202/native/aarch64/keccak_f1600_x2_v84a_asm_clean.S b/fips202/native/aarch64/src/keccak_f1600_x2_v84a_asm_clean.S similarity index 98% rename from fips202/native/aarch64/keccak_f1600_x2_v84a_asm_clean.S rename to fips202/native/aarch64/src/keccak_f1600_x2_v84a_asm_clean.S index f74856a5f..45304aa25 100644 --- a/fips202/native/aarch64/keccak_f1600_x2_v84a_asm_clean.S +++ b/fips202/native/aarch64/src/keccak_f1600_x2_v84a_asm_clean.S @@ -37,8 +37,9 @@ // during load and store, so that the caller need not do this. // -#include "config.h" -#if defined(MLKEM_USE_NATIVE_AARCH64) +#include "common.h" +#if defined(MLKEM_NATIVE_FIPS202_BACKEND_AARCH64_DEFAULT) || \ + defined(MLKEM_NATIVE_FIPS202_BACKEND_AARCH64_A55) // Needed to provide ASM_LOAD directive #include "common.i" diff --git a/fips202/native/aarch64/keccak_f1600_x2_v8a_v84a_asm_hybrid.S b/fips202/native/aarch64/src/keccak_f1600_x2_v8a_v84a_asm_hybrid.S similarity index 98% rename from fips202/native/aarch64/keccak_f1600_x2_v8a_v84a_asm_hybrid.S rename to fips202/native/aarch64/src/keccak_f1600_x2_v8a_v84a_asm_hybrid.S index b7cc6f261..e4fecb11d 100644 --- a/fips202/native/aarch64/keccak_f1600_x2_v8a_v84a_asm_hybrid.S +++ b/fips202/native/aarch64/src/keccak_f1600_x2_v8a_v84a_asm_hybrid.S @@ -37,12 +37,12 @@ // during load and store, so that the caller need not do this. // -#include "config.h" -#if defined(MLKEM_USE_NATIVE_AARCH64) +#include "common.h" +#if defined(MLKEM_NATIVE_FIPS202_BACKEND_AARCH64_DEFAULT) || \ + defined(MLKEM_NATIVE_FIPS202_BACKEND_AARCH64_A55) // Needed to provide ASM_LOAD directive #include "common.i" -#include "namespace.h" #if defined(__ARM_FEATURE_SHA3) diff --git a/fips202/native/aarch64/keccak_f1600_x4_scalar_v84a_asm_hybrid_opt.S b/fips202/native/aarch64/src/keccak_f1600_x4_scalar_v84a_asm_hybrid_opt.S similarity index 99% rename from fips202/native/aarch64/keccak_f1600_x4_scalar_v84a_asm_hybrid_opt.S rename to fips202/native/aarch64/src/keccak_f1600_x4_scalar_v84a_asm_hybrid_opt.S index 19a93b9e8..abf1af497 100644 --- a/fips202/native/aarch64/keccak_f1600_x4_scalar_v84a_asm_hybrid_opt.S +++ b/fips202/native/aarch64/src/keccak_f1600_x4_scalar_v84a_asm_hybrid_opt.S @@ -24,12 +24,12 @@ * */ -#include "config.h" -#if defined(MLKEM_USE_NATIVE_AARCH64) +#include "common.h" +#if defined(MLKEM_NATIVE_FIPS202_BACKEND_AARCH64_DEFAULT) || \ + defined(MLKEM_NATIVE_FIPS202_BACKEND_AARCH64_A55) // Needed to provide ASM_LOAD directive #include "common.i" -#include "namespace.h" #if defined(__ARM_FEATURE_SHA3) diff --git a/fips202/native/aarch64/keccak_f1600_x4_v8a_scalar_hybrid_asm_opt.S b/fips202/native/aarch64/src/keccak_f1600_x4_v8a_scalar_hybrid_asm_opt.S similarity index 99% rename from fips202/native/aarch64/keccak_f1600_x4_v8a_scalar_hybrid_asm_opt.S rename to fips202/native/aarch64/src/keccak_f1600_x4_v8a_scalar_hybrid_asm_opt.S index a32375f07..f001d3eaf 100644 --- a/fips202/native/aarch64/keccak_f1600_x4_v8a_scalar_hybrid_asm_opt.S +++ b/fips202/native/aarch64/src/keccak_f1600_x4_v8a_scalar_hybrid_asm_opt.S @@ -24,12 +24,12 @@ * */ -#include "config.h" -#if defined(MLKEM_USE_NATIVE_AARCH64) +#include "common.h" +#if defined(MLKEM_NATIVE_FIPS202_BACKEND_AARCH64_DEFAULT) || \ + defined(MLKEM_NATIVE_FIPS202_BACKEND_AARCH64_A55) // Needed to provide ASM_LOAD directive #include "common.i" -#include "namespace.h" #define KECCAK_F1600_ROUNDS 24 diff --git a/fips202/native/aarch64/keccak_f1600_x4_v8a_v84a_scalar_hybrid_asm_opt.S b/fips202/native/aarch64/src/keccak_f1600_x4_v8a_v84a_scalar_hybrid_asm_opt.S similarity index 99% rename from fips202/native/aarch64/keccak_f1600_x4_v8a_v84a_scalar_hybrid_asm_opt.S rename to fips202/native/aarch64/src/keccak_f1600_x4_v8a_v84a_scalar_hybrid_asm_opt.S index 889ba2983..67a0adccd 100644 --- a/fips202/native/aarch64/keccak_f1600_x4_v8a_v84a_scalar_hybrid_asm_opt.S +++ b/fips202/native/aarch64/src/keccak_f1600_x4_v8a_v84a_scalar_hybrid_asm_opt.S @@ -24,8 +24,9 @@ * */ -#include "config.h" -#if defined(MLKEM_USE_NATIVE_AARCH64) +#include "common.h" +#if defined(MLKEM_NATIVE_FIPS202_BACKEND_AARCH64_DEFAULT) || \ + defined(MLKEM_NATIVE_FIPS202_BACKEND_AARCH64_A55) // Needed to provide ASM_LOAD directive #include "common.i" diff --git a/fips202/native/api.h b/fips202/native/api.h new file mode 100644 index 000000000..685b8bfc5 --- /dev/null +++ b/fips202/native/api.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2024 The mlkem-native project authors + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef FIPS202_NATIVE_H +#define FIPS202_NATIVE_H + +#include +#include "common.h" + +/* + * FIPS202 native interface + */ + +/* + * Those functions are meant to be trivial wrappers around + * the chosen native implementation. The are static inline + * to avoid unnecessary calls. + * The macro before each declaration controls whether a native + * implementation is present. + */ + +#if defined(MLKEM_USE_FIPS202_X1_NATIVE) +static INLINE void keccak_f1600_x1_native(uint64_t *state); +#endif +#if defined(MLKEM_USE_FIPS202_X2_NATIVE) +static INLINE void keccak_f1600_x2_native(uint64_t *state); +#endif +#if defined(MLKEM_USE_FIPS202_X4_NATIVE) +static INLINE void keccak_f1600_x4_native(uint64_t *state); +#endif + +#endif /* FIPS202_NATIVE_H */ diff --git a/fips202/native/default.h b/fips202/native/default.h new file mode 100644 index 000000000..41c068910 --- /dev/null +++ b/fips202/native/default.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2024 The mlkem-native project authors + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef MLKEM_NATIVE_FIPS202_BACKEND_DEFAULT_H +#define MLKEM_NATIVE_FIPS202_BACKEND_DEFAULT_H + +/* + * Default FIPS202 backend + */ +#include "sys.h" + +#if defined(SYS_AARCH64) +#include "aarch64/default.h" +#endif + +#if defined(SYS_X86_64) && defined(SYS_X86_64_AVX2) +#include "x86_64/xkcp.h" +#endif + +#endif /* MLKEM_NATIVE_FIPS202_BACKEND_DEFAULT_H */ diff --git a/fips202/native/fips202_native.h b/fips202/native/fips202_native.h deleted file mode 100644 index ccddc32a9..000000000 --- a/fips202/native/fips202_native.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2024 The mlkem-native project authors - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef FIPS202_NATIVE_H -#define FIPS202_NATIVE_H - -#include -#include "config.h" -#include "params.h" - -#if defined(MLKEM_USE_NATIVE) - -/* - * FIPS202 native profile - * - * The profile decides which implementation(s) of FIPS202 to use. - * - * If you don't change anything, the default profile will be used. This profile - * picks implementations based on characteristics of your system visible to - * the compiler. - * - * The default logic is not perfect, and you may want to pick a specific - * profile for your target. There are three ways to do so, in descending - * order of convenience to the user: - * 1. Pick one of the profiles shipped with this repository. - * 2. Provide your own profile and register it via FIPS202_ASM_PROFILE - * (which must be the profile's path relative to this directoru). - * 3. Set FIPS202_NATIVE_MANUAL and use an adhoc profile specified via CFLAGS. - */ - -/* Option 2: Manually written profile */ -#if defined(FIPS202_NATIVE_PROFILE) - -#define STRINGIFY_(x) #x -#define STRINGIFY(x) STRINGIFY_(x) -#include STRINGIFY(FIPS202_NATIVE_PROFILE) - -/* Option 1: Choose from shipped list of profiles */ -#elif !defined(FIPS202_NATIVE_MANUAL) - -#ifdef SYS_AARCH64 -/* Pick exactly one profile from the following list */ -#include "aarch64/profiles/default.h" -/* #include "aarch64/profiles/cortex_a55.h" */ -#endif - -#if defined(SYS_X86_64) && defined(SYS_X86_64_AVX2) -#include "x86_64/profiles/xkcp.h" -#endif - -#else /* !FIPS202_NATIVE_PROFILE && FIPS202_NATIVE_MANUAL */ - -/* Option 3: Build your own profile here, or via CFLAGS */ - -#endif /* !FIPS202_NATIVE_PROFILE && !FIPS202_NATIVE_MANUAL */ - -/* - * FIPS202 native interface - */ - -/* - * Those functions are meant to be trivial wrappers around - * the chosen native implementation. The are static inline - * to avoid unnecessary calls. - * The macro before each declaration controls whether a native - * implementation is present. - */ - -#if defined(MLKEM_USE_FIPS202_X1_NATIVE) -static INLINE void keccak_f1600_x1_native(uint64_t *state); -#endif -#if defined(MLKEM_USE_FIPS202_X2_NATIVE) -static INLINE void keccak_f1600_x2_native(uint64_t *state); -#endif -#if defined(MLKEM_USE_FIPS202_X4_NATIVE) -static INLINE void keccak_f1600_x4_native(uint64_t *state); -#endif - -#endif /* MLKEM_USE_NATIVE */ -#endif /* FIPS202_NATIVE_H */ diff --git a/fips202/native/x86_64/fips202_native_x86_64.h b/fips202/native/x86_64/fips202_native_x86_64.h deleted file mode 100644 index cbc0bb97d..000000000 --- a/fips202/native/x86_64/fips202_native_x86_64.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2024 The mlkem-native project authors - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef FIPS202_X86_64_NATIVE_H -#define FIPS202_X86_64_NATIVE_H - -#include "config.h" - -#ifdef MLKEM_USE_NATIVE_X86_64 - -#include -#include -#include - -#include "xkcp/KeccakP-1600-times4-SnP.h" - -#endif /* MLKEM_USE_NATIVE_X86_64 */ - -#endif /* FIPS202_X86_64_NATIVE_H */ diff --git a/fips202/native/x86_64/xkcp/KeccakP-1600-times4-SIMD256.c b/fips202/native/x86_64/src/KeccakP-1600-times4-SIMD256.c similarity index 99% rename from fips202/native/x86_64/xkcp/KeccakP-1600-times4-SIMD256.c rename to fips202/native/x86_64/src/KeccakP-1600-times4-SIMD256.c index 9a36f17aa..d56823ab3 100644 --- a/fips202/native/x86_64/xkcp/KeccakP-1600-times4-SIMD256.c +++ b/fips202/native/x86_64/src/KeccakP-1600-times4-SIMD256.c @@ -24,8 +24,8 @@ and related or neighboring rights to the source code in this file. * Keccak states in memory. */ -#include "config.h" -#if defined(MLKEM_USE_NATIVE_X86_64) && defined(SYS_X86_64_AVX2) +#include "common.h" +#if defined(MLKEM_NATIVE_FIPS202_BACKEND_X86_64_XKCP) #include #include @@ -445,10 +445,9 @@ void KeccakP1600times4_PermuteAll_24rounds(void *states) } #else -#include "params.h" /* Dummy constant to keep compiler happy despite empty CU */ -#define empty_cu_avx2_keccakx4 MLKEM_NAMESPACE(empty_cu_avx2_keccakx4) +#define empty_cu_avx2_keccakx4 FIPS202_NAMESPACE(empty_cu_avx2_keccakx4) int empty_cu_avx2_keccakx4; -#endif /* MLKEM_USE_NATIVE_X86_64 && SYS_X86_64_AVX2 */ +#endif /* MLKEM_NATIVE_FIPS202_BACKEND_X86_64_XKCP */ diff --git a/fips202/native/x86_64/xkcp/KeccakP-1600-times4-SnP.h b/fips202/native/x86_64/src/KeccakP-1600-times4-SnP.h similarity index 97% rename from fips202/native/x86_64/xkcp/KeccakP-1600-times4-SnP.h rename to fips202/native/x86_64/src/KeccakP-1600-times4-SnP.h index 6d1951787..0738c9488 100644 --- a/fips202/native/x86_64/xkcp/KeccakP-1600-times4-SnP.h +++ b/fips202/native/x86_64/src/KeccakP-1600-times4-SnP.h @@ -26,7 +26,7 @@ and related or neighboring rights to the source code in this file. #include #include "KeccakP-SIMD256-config.h" -#include "namespace.h" +#include "common.h" #define KeccakP1600times4_statesAlignment 32 diff --git a/fips202/native/x86_64/xkcp/KeccakP-1600-unrolling.macros b/fips202/native/x86_64/src/KeccakP-1600-unrolling.macros similarity index 100% rename from fips202/native/x86_64/xkcp/KeccakP-1600-unrolling.macros rename to fips202/native/x86_64/src/KeccakP-1600-unrolling.macros diff --git a/fips202/native/x86_64/xkcp/KeccakP-SIMD256-config.h b/fips202/native/x86_64/src/KeccakP-SIMD256-config.h similarity index 100% rename from fips202/native/x86_64/xkcp/KeccakP-SIMD256-config.h rename to fips202/native/x86_64/src/KeccakP-SIMD256-config.h diff --git a/fips202/native/x86_64/xkcp/KeccakP-align.h b/fips202/native/x86_64/src/KeccakP-align.h similarity index 100% rename from fips202/native/x86_64/xkcp/KeccakP-align.h rename to fips202/native/x86_64/src/KeccakP-align.h diff --git a/fips202/native/x86_64/xkcp/KeccakP-brg_endian.h b/fips202/native/x86_64/src/KeccakP-brg_endian.h similarity index 100% rename from fips202/native/x86_64/xkcp/KeccakP-brg_endian.h rename to fips202/native/x86_64/src/KeccakP-brg_endian.h diff --git a/fips202/native/x86_64/profiles/xkcp.h b/fips202/native/x86_64/src/xkcp_impl.h similarity index 60% rename from fips202/native/x86_64/profiles/xkcp.h rename to fips202/native/x86_64/src/xkcp_impl.h index 4f320e994..c0ad76850 100644 --- a/fips202/native/x86_64/profiles/xkcp.h +++ b/fips202/native/x86_64/src/xkcp_impl.h @@ -5,14 +5,12 @@ /* Default FIPS202 assembly profile for AArch64 systems */ -#ifdef FIPS202_NATIVE_PROFILE_H +#ifdef MLKEM_NATIVE_FIPS202_PROFILE_IMPL_H #error Only one FIPS202 assembly profile can be defined -- did you include multiple profiles? #else -#define FIPS202_NATIVE_PROFILE_H +#define MLKEM_NATIVE_FIPS202_PROFILE_IMPL_H -#include "../fips202_native_x86_64.h" - -#if defined(MLKEM_USE_NATIVE_X86_64) && defined(SYS_X86_64_AVX2) +#include "KeccakP-1600-times4-SnP.h" #define MLKEM_USE_FIPS202_X4_NATIVE static INLINE void keccak_f1600_x4_native(uint64_t *state) @@ -20,6 +18,4 @@ static INLINE void keccak_f1600_x4_native(uint64_t *state) KeccakP1600times4_PermuteAll_24rounds(state); } -#endif /* MLKEM_USE_NATIVE_X86_64 && SYS_X86_64_AVX2 */ - -#endif /* FIPS202_NATIVE_PROFILE_H */ +#endif /* MLKEM_NATIVE_FIPS202_PROFILE_IMPL_H */ diff --git a/fips202/native/x86_64/xkcp.h b/fips202/native/x86_64/xkcp.h new file mode 100644 index 000000000..1cfcee9fd --- /dev/null +++ b/fips202/native/x86_64/xkcp.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024 The mlkem-native project authors + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Default FIPS202 assembly profile for AArch64 systems */ + +#ifdef MLKEM_NATIVE_FIPS202_PROFILE_H +#error Only one FIPS202 assembly profile can be defined -- did you include multiple profiles? +#else +#define MLKEM_NATIVE_FIPS202_PROFILE_H + +/* Identifier for this backend so that source and assembly files + * in the build can be appropriately guarded. */ +#define MLKEM_NATIVE_FIPS202_BACKEND_X86_64_XKCP + +#define MLKEM_NATIVE_FIPS202_BACKEND_NAME X86_64_XKCP + +/* Filename of the C backend implementation. + * This is not inlined here because this header is included in assembly + * files as well. */ +#define MLKEM_NATIVE_FIPS202_BACKEND_IMPL "x86_64/src/xkcp_impl.h" + +#endif /* MLKEM_NATIVE_FIPS202_PROFILE_H */ diff --git a/mk/crypto.mk b/mk/crypto.mk index faf0eb047..9cb04227d 100644 --- a/mk/crypto.mk +++ b/mk/crypto.mk @@ -2,7 +2,7 @@ CPPFLAGS += -Ifips202 -Ifips202/native FIPS202_SRCS = $(wildcard fips202/*.c) ifeq ($(OPT),1) - FIPS202_SRCS += $(wildcard fips202/native/aarch64/*.S) $(wildcard fips202/native/x86_64/xkcp/*.c) + FIPS202_SRCS += $(wildcard fips202/native/aarch64/src/*.S) $(wildcard fips202/native/x86_64/src/*.c) endif $(BUILD_DIR)/libmlkem.a: $(call OBJS, $(FIPS202_SRCS)) diff --git a/mk/schemes.mk b/mk/schemes.mk index deabcdd86..ede00a635 100644 --- a/mk/schemes.mk +++ b/mk/schemes.mk @@ -1,7 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 SOURCES += $(wildcard mlkem/*.c) $(wildcard mlkem/debug/*.c) ifeq ($(OPT),1) - SOURCES += $(wildcard mlkem/native/aarch64/*.[csS]) $(wildcard mlkem/native/x86_64/*.[csS]) + SOURCES += $(wildcard mlkem/native/aarch64/src/*.[csS]) $(wildcard mlkem/native/x86_64/src/*.[csS]) CPPFLAGS += -DMLKEM_USE_NATIVE endif diff --git a/mlkem/api.h b/mlkem/api.h deleted file mode 100644 index 94597323f..000000000 --- a/mlkem/api.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2024 The mlkem-native project authors - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef API_H -#define API_H - -#include - -#define PQCP_MLKEM_NATIVE_MLKEM512_SECRETKEYBYTES 1632 -#define PQCP_MLKEM_NATIVE_MLKEM512_PUBLICKEYBYTES 800 -#define PQCP_MLKEM_NATIVE_MLKEM512_CIPHERTEXTBYTES 768 -#define PQCP_MLKEM_NATIVE_MLKEM512_KEYPAIRCOINBYTES 64 -#define PQCP_MLKEM_NATIVE_MLKEM512_ENCCOINBYTES 32 -#define PQCP_MLKEM_NATIVE_MLKEM512_BYTES 32 - -int PQCP_MLKEM_NATIVE_MLKEM512_keypair_derand(uint8_t *pk, uint8_t *sk, - const uint8_t *coins); -int PQCP_MLKEM_NATIVE_MLKEM512_keypair(uint8_t *pk, uint8_t *sk); -int PQCP_MLKEM_NATIVE_MLKEM512_enc_derand(uint8_t *ct, uint8_t *ss, - const uint8_t *pk, - const uint8_t *coins); -int PQCP_MLKEM_NATIVE_MLKEM512_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk); -int PQCP_MLKEM_NATIVE_MLKEM512_dec(uint8_t *ss, const uint8_t *ct, - const uint8_t *sk); - -#define PQCP_MLKEM_NATIVE_MLKEM768_SECRETKEYBYTES 2400 -#define PQCP_MLKEM_NATIVE_MLKEM768_PUBLICKEYBYTES 1184 -#define PQCP_MLKEM_NATIVE_MLKEM768_CIPHERTEXTBYTES 1088 -#define PQCP_MLKEM_NATIVE_MLKEM768_KEYPAIRCOINBYTES 64 -#define PQCP_MLKEM_NATIVE_MLKEM768_ENCCOINBYTES 32 -#define PQCP_MLKEM_NATIVE_MLKEM768_BYTES 32 - -int PQCP_MLKEM_NATIVE_MLKEM768_keypair_derand(uint8_t *pk, uint8_t *sk, - const uint8_t *coins); -int PQCP_MLKEM_NATIVE_MLKEM768_keypair(uint8_t *pk, uint8_t *sk); -int PQCP_MLKEM_NATIVE_MLKEM768_enc_derand(uint8_t *ct, uint8_t *ss, - const uint8_t *pk, - const uint8_t *coins); -int PQCP_MLKEM_NATIVE_MLKEM768_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk); -int PQCP_MLKEM_NATIVE_MLKEM768_dec(uint8_t *ss, const uint8_t *ct, - const uint8_t *sk); - -#define PQCP_MLKEM_NATIVE_MLKEM1024_SECRETKEYBYTES 3168 -#define PQCP_MLKEM_NATIVE_MLKEM1024_PUBLICKEYBYTES 1568 -#define PQCP_MLKEM_NATIVE_MLKEM1024_CIPHERTEXTBYTES 1568 -#define PQCP_MLKEM_NATIVE_MLKEM1024_KEYPAIRCOINBYTES 64 -#define PQCP_MLKEM_NATIVE_MLKEM1024_ENCCOINBYTES 32 -#define PQCP_MLKEM_NATIVE_MLKEM1024_BYTES 32 - -int PQCP_MLKEM_NATIVE_MLKEM1024_keypair_derand(uint8_t *pk, uint8_t *sk, - const uint8_t *coins); -int PQCP_MLKEM_NATIVE_MLKEM1024_keypair(uint8_t *pk, uint8_t *sk); -int PQCP_MLKEM_NATIVE_MLKEM1024_enc_derand(uint8_t *ct, uint8_t *ss, - const uint8_t *pk, - const uint8_t *coins); -int PQCP_MLKEM_NATIVE_MLKEM1024_enc(uint8_t *ct, uint8_t *ss, - const uint8_t *pk); -int PQCP_MLKEM_NATIVE_MLKEM1024_dec(uint8_t *ss, const uint8_t *ct, - const uint8_t *sk); - -#endif diff --git a/mlkem/arith_backend.h b/mlkem/arith_backend.h new file mode 100644 index 000000000..7fb3df84d --- /dev/null +++ b/mlkem/arith_backend.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2024 The mlkem-native project authors + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifdef MLKEM_NATIVE_ARITH_IMPL_H +#error Only one ARITH assembly profile can be defined -- did you include multiple profiles? +#else +#define MLKEM_NATIVE_ARITH_IMPL_H + +/* Include to enforce consistency of API and implementation */ +#include "native/api.h" + +#if defined(MLKEM_NATIVE_ARITH_BACKEND_IMPL) +#include MLKEM_NATIVE_ARITH_BACKEND_IMPL +#endif + +#endif /* MLKEM_NATIVE_ARITH_IMPL_H */ diff --git a/mlkem/cbd.c b/mlkem/cbd.c index 073f3c81d..2e0fac38a 100644 --- a/mlkem/cbd.c +++ b/mlkem/cbd.c @@ -4,7 +4,6 @@ */ #include "cbd.h" #include -#include "params.h" /************************************************* * Name: load32_littleendian diff --git a/mlkem/cbd.h b/mlkem/cbd.h index 4dc8635bb..31c9649e3 100644 --- a/mlkem/cbd.h +++ b/mlkem/cbd.h @@ -6,7 +6,7 @@ #define CBD_H #include -#include "params.h" +#include "common.h" #include "poly.h" #define poly_cbd_eta1 MLKEM_NAMESPACE(poly_cbd_eta1) diff --git a/mlkem/common.h b/mlkem/common.h index 94c29ed92..3469d2739 100644 --- a/mlkem/common.h +++ b/mlkem/common.h @@ -2,64 +2,28 @@ * Copyright (c) 2024 The mlkem-native project authors * SPDX-License-Identifier: Apache-2.0 */ -#ifndef COMMON_H -#define COMMON_H +#ifndef MLKEM_NATIVE_COMMON_H +#define MLKEM_NATIVE_COMMON_H +#if defined(MLKEM_NATIVE_CONFIG_FILE) +#include MLKEM_NATIVE_CONFIG_FILE +#endif /* MLKEM_NATIVE_CONFIG_FILE */ -/* - * C90 does not have the inline compiler directive yet. - * We don't use it in C90 builds. - * However, in that case the compiler warns about some inline functions in - * header files not being used in every compilation unit that includes that - * header. To work around it we silence that warning in that case using - * __attribute__((unused)). - */ +#include "params.h" +#include "sys.h" -/* Do not use inline for C90 builds*/ -#if !defined(inline) -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L -#define INLINE inline -#define ALWAYS_INLINE __attribute__((always_inline)) -#elif defined(_MSC_VER) -#define INLINE __inline -#define ALWAYS_INLINE __forceinline -#else -#define INLINE __attribute__((unused)) -#define ALWAYS_INLINE +/* Include backend metadata */ +#if defined(MLKEM_USE_NATIVE) +#if defined(MLKEM_NATIVE_ARITH_BACKEND) +#include MLKEM_NATIVE_ARITH_BACKEND #endif - -#else -#define INLINE inline -#define ALWAYS_INLINE __attribute__((always_inline)) +#if defined(MLKEM_NATIVE_FIPS202_BACKEND) +#include MLKEM_NATIVE_FIPS202_BACKEND #endif - - -/* - * C90 does not have the restrict compiler directive yet. - * We don't use it in C90 builds. - */ -#if !defined(restrict) -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L -#define RESTRICT restrict -#else -#define RESTRICT #endif -#else +/* This must come after the inclusion of the backend metadata + * since the backend choice may be part of the namespace. */ +#include "namespace.h" -#define RESTRICT restrict -#endif - -#define DEFAULT_ALIGN 32 -#if defined(_WIN32) -#define ALIGN __declspec(align(DEFAULT_ALIGN)) -#define asm __asm -#else -#define asm __asm__ -#define ALIGN __attribute__((aligned(DEFAULT_ALIGN))) -#endif - -#define MLKEM_CONCAT_(left, right) left##right -#define MLKEM_CONCAT(left, right) MLKEM_CONCAT_(left, right) - -#endif +#endif /* MLKEM_NATIVE_COMMON_H */ diff --git a/mlkem/config.h b/mlkem/config.h new file mode 100644 index 000000000..fae77e719 --- /dev/null +++ b/mlkem/config.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2024 The mlkem-native project authors + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef MLKEM_NATIVE_CONFIG_H +#define MLKEM_NATIVE_CONFIG_H + +/****************************************************************************** + * Name: MLKEM_K + * + * Description: Determines the security level for ML-KEM + * - MLKEM_K=2 corresponds to ML-KEM-512 + * - MLKEM_K=3 corresponds to ML-KEM-768 + * - MLKEM_K=4 corresponds to ML-KEM-1024 + * + * This can also be set using CFLAGS. + * + *****************************************************************************/ +#ifndef MLKEM_K +#define MLKEM_K 3 /* Change this for different security strengths */ +#endif + +/****************************************************************************** + * Name: MLKEM_NATIVE_CONFIG_FILE + * + * Description: If defined, this is a header that will be included instead + * of mlkem/config.h. + * + * This _must_ be set on the command line using + * `-DMLKEM_NATIVE_CONFIG_FILE="..."`. + * + * When you need to build mlkem-native in multiple configurations, + * using varying MLKEM_NATIE_CONFIG_FILE can be more convenient + * then configuring everything through CFLAGS. + * + *****************************************************************************/ +/* #define MLKEM_NATIVE_CONFIG_FILE "config.h" */ + +/****************************************************************************** + * Name: MLKEM_NAMESPACE + * _MLKEM_NAMESPACE + * + * Description: The macros to use to namespace global symbols + * from mlkem/. + *****************************************************************************/ +#define MLKEM_NAMESPACE(sym) MLKEM_DEFAULT_NAMESPACE(sym) +#define _MLKEM_NAMESPACE(sym) _MLKEM_DEFAULT_NAMESPACE(sym) + +/****************************************************************************** + * Name: FIPS202_NAMESPACE + * _FIPS202_NAMESPACE + * + * Description: The macros to use to namespace global symbols + * from fips202/. + *****************************************************************************/ +#define FIPS202_NAMESPACE(sym) FIPS202_DEFAULT_NAMESPACE(sym) +#define _FIPS202_NAMESPACE(sym) _FIPS202_DEFAULT_NAMESPACE(sym) + +/****************************************************************************** + * Name: MLKEM_USE_NATIVE + * + * Description: Determines whether a native backend should + * be used, if available. + * + * This can also be set using CFLAGS. + * + *****************************************************************************/ +#if !defined(MLKEM_USE_NATIVE) +/* #define MLKEM_USE_NATIVE */ +#endif + +/****************************************************************************** + * Name: MLKEM_NATIVE_ARITH_BACKEND + * + * Description: The arithmetic backend to use. + * + * This must be the filename of an arithmetic backend. + * See the existing backends for examples. + * + * This can be set using CFLAGS. + * + *****************************************************************************/ +#if defined(MLKEM_USE_NATIVE) && !defined(MLKEM_NATIVE_ARITH_BACKEND) +#define MLKEM_NATIVE_ARITH_BACKEND "native/default.h" +#endif /* MLKEM_NATIVE_ARITH_BACKEND */ + +/****************************************************************************** + * Name: MLKEM_NATIVE_FIPS202_BACKEND + * + * Description: The FIPS-202 backend to use. + * + * This must be the filename of an FIPS-202 backend. + * + * This can be set using CFLAGS. + * + *****************************************************************************/ +#if defined(MLKEM_USE_NATIVE) && !defined(MLKEM_NATIVE_FIPS202_BACKEND) +#define MLKEM_NATIVE_FIPS202_BACKEND "../fips202/native/default.h" +#endif /* MLKEM_NATIVE_FIPS202_BACKEND */ + +#endif /* MLkEM_NATIVE_CONFIG_H */ diff --git a/mlkem/debug/debug.c b/mlkem/debug/debug.c index 0dc2e8822..690977908 100644 --- a/mlkem/debug/debug.c +++ b/mlkem/debug/debug.c @@ -52,7 +52,6 @@ void mlkem_debug_print_error(const char *file, int line, const char *msg) } #else /* MLKEM_DEBUG */ -#include "params.h" #define empty_cu_debug MLKEM_NAMESPACE(empty_cu_debug) int empty_cu_debug; diff --git a/mlkem/debug/debug.h b/mlkem/debug/debug.h index 65208771d..5838ae4bf 100644 --- a/mlkem/debug/debug.h +++ b/mlkem/debug/debug.h @@ -5,6 +5,8 @@ #ifndef MLKEM_DEBUG_H #define MLKEM_DEBUG_H +#include "common.h" + #if defined(MLKEM_DEBUG) #include #include @@ -153,6 +155,9 @@ void mlkem_debug_print_error(const char *file, int line, const char *msg); "polyvec unsigned bound for " #ptr ".vec[i]"); \ } while (0) +#define MLKEM_CONCAT_(left, right) left##right +#define MLKEM_CONCAT(left, right) MLKEM_CONCAT_(left, right) + /* Following AWS-LC to define a C99-compliant static assert */ #define MLKEM_STATIC_ASSERT_DEFINE(cond, msg) \ typedef struct \ diff --git a/mlkem/indcpa.c b/mlkem/indcpa.c index bde832c18..ee2f140a0 100644 --- a/mlkem/indcpa.c +++ b/mlkem/indcpa.c @@ -10,14 +10,13 @@ #include "fips202x4.h" #include "indcpa.h" #include "ntt.h" -#include "params.h" #include "poly.h" #include "polyvec.h" #include "randombytes.h" #include "rej_uniform.h" #include "symmetric.h" -#include "arith_native.h" +#include "arith_backend.h" #include "debug/debug.h" #include "cbmc.h" diff --git a/mlkem/indcpa.h b/mlkem/indcpa.h index 0e6485312..7e2a0b247 100644 --- a/mlkem/indcpa.h +++ b/mlkem/indcpa.h @@ -7,10 +7,9 @@ #include #include "cbmc.h" -#include "params.h" +#include "common.h" #include "polyvec.h" - #define gen_matrix MLKEM_NAMESPACE(gen_matrix) /************************************************* * Name: gen_matrix diff --git a/mlkem/kem.c b/mlkem/kem.c index 1abce65e4..03e997af3 100644 --- a/mlkem/kem.c +++ b/mlkem/kem.c @@ -7,7 +7,6 @@ #include #include #include "indcpa.h" -#include "params.h" #include "randombytes.h" #include "symmetric.h" #include "verify.h" diff --git a/mlkem/namespace.h b/mlkem/namespace.h new file mode 100644 index 000000000..8c409fb0c --- /dev/null +++ b/mlkem/namespace.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2024 The mlkem-native project authors + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef MLKEM_NATIVE_NAMESPACE_H +#define MLKEM_NATIVE_NAMESPACE_H + +#if !defined(MLKEM_NATIVE_ARITH_BACKEND_NAME) +#define MLKEM_NATIVE_ARITH_BACKEND_NAME C +#endif + +/* Don't change parameters below this line */ +#if (MLKEM_K == 2) +#define MLKEM_PARAM_NAME MLKEM512 +#elif (MLKEM_K == 3) +#define MLKEM_PARAM_NAME MLKEM768 +#elif (MLKEM_K == 4) +#define MLKEM_PARAM_NAME MLKEM1024 +#else +#error "MLKEM_K must be in {2,3,4}" +#endif + +#define ___MLKEM_DEFAULT_NAMESPACE(x1, x2, x3, x4) x1##_##x2##_##x3##_##x4 +#define __MLKEM_DEFAULT_NAMESPACE(x1, x2, x3, x4) \ + ___MLKEM_DEFAULT_NAMESPACE(x1, x2, x3, x4) + +/* + * NAMESPACE is PQCP_MLKEM_NATIVE___ + * e.g., PQCP_MLKEM_NATIVE_MLKEM512_AARCH64_OPT_ + */ +#define MLKEM_DEFAULT_NAMESPACE(s) \ + __MLKEM_DEFAULT_NAMESPACE(PQCP_MLKEM_NATIVE, MLKEM_PARAM_NAME, \ + MLKEM_NATIVE_ARITH_BACKEND_NAME, s) +#define _MLKEM_DEFAULT_NAMESPACE(s) \ + __MLKEM_DEFAULT_NAMESPACE(_PQCP_MLKEM_NATIVE, MLKEM_PARAM_NAME, \ + MLKEM_NATIVE_ARITH_BACKEND_NAME, s) + +#if !defined(MLKEM_NATIVE_FIPS202_BACKEND_NAME) +#define MLKEM_NATIVE_FIPS202_BACKEND_NAME C +#endif + +#define ___FIPS202_DEFAULT_NAMESPACE(x1, x2, x3) x1##_##x2##_##x3 +#define __FIPS202_DEFAULT_NAMESPACE(x1, x2, x3) \ + ___FIPS202_DEFAULT_NAMESPACE(x1, x2, x3) + +/* + * NAMESPACE is PQCP_MLKEM_NATIVE_FIPS202__ + * e.g., PQCP_MLKEM_NATIVE_FIPS202_X86_64_XKCP_ + */ +#define FIPS202_DEFAULT_NAMESPACE(s) \ + __FIPS202_DEFAULT_NAMESPACE(PQCP_MLKEM_NATIVE_FIPS202, \ + MLKEM_NATIVE_FIPS202_BACKEND_NAME, s) +#define _FIPS202_DEFAULT_NAMESPACE(s) \ + __FIPS202_DEFAULT_NAMESPACE(_PQCP_MLKEM_NATIVE_FIPS202, \ + MLKEM_NATIVE_FIPS202_BACKEND_NAME, s) + +#endif /* MLKEM_NATIVE_NAMESPACE_H */ diff --git a/mlkem/native/aarch64/README.md b/mlkem/native/aarch64/README.md index c21e27f36..e499a4a22 100644 --- a/mlkem/native/aarch64/README.md +++ b/mlkem/native/aarch64/README.md @@ -16,4 +16,4 @@ This backend comes with two profiles: "clean" and optimized. The "clean" backend read and modify; for example, is heavily leverages register aliases and assembly macros. The optimized profile is automatically generated from the clean profile via [SLOTHY](https://github.com/slothy-optimizer/slothy). Currently, the target architecture is Cortex-A55, but you can easily re-optimize the code for a different microarchitecture supported -by SLOTHY, by adjusting the parameters in [optimize.sh](optimize.sh). +by SLOTHY, by adjusting the parameters in [optimize.sh](src/optimize.sh). diff --git a/mlkem/native/aarch64/clean.h b/mlkem/native/aarch64/clean.h new file mode 100644 index 000000000..43a401dfc --- /dev/null +++ b/mlkem/native/aarch64/clean.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024 The mlkem-native project authors + * SPDX-License-Identifier: Apache-2.0 + */ + +/* ML-KEM arithmetic native profile for clean assembly */ + +#ifdef MLKEM_NATIVE_ARITH_PROFILE_H +#error Only one MLKEM_ARITH assembly profile can be defined -- did you include multiple profiles? +#else +#define MLKEM_NATIVE_ARITH_PROFILE_H + +/* Identifier for this backend so that source and assembly files + * in the build can be appropriately guarded. */ +#define MLKEM_NATIVE_ARITH_BACKEND_AARCH64_CLEAN + +#define MLKEM_NATIVE_ARITH_BACKEND_NAME AARCH64_CLEAN + +/* Filename of the C backend implementation. + * This is not inlined here because this header is included in assembly + * files as well. */ +#define MLKEM_NATIVE_ARITH_BACKEND_IMPL "aarch64/src/clean_impl.h" + +#endif /* MLKEM_NATIVE_ARITH_PROFILE_H */ diff --git a/mlkem/native/aarch64/opt.h b/mlkem/native/aarch64/opt.h new file mode 100644 index 000000000..04323c3e7 --- /dev/null +++ b/mlkem/native/aarch64/opt.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024 The mlkem-native project authors + * SPDX-License-Identifier: Apache-2.0 + */ + +/* ML-KEM arithmetic native profile for clean assembly */ + +#ifdef MLKEM_NATIVE_ARITH_PROFILE_H +#error Only one MLKEM_ARITH assembly profile can be defined -- did you include multiple profiles? +#else +#define MLKEM_NATIVE_ARITH_PROFILE_H + +/* Identifier for this backend so that source and assembly files + * in the build can be appropriately guarded. */ +#define MLKEM_NATIVE_ARITH_BACKEND_AARCH64_OPT + +#define MLKEM_NATIVE_ARITH_BACKEND_NAME AARCH64_OPT + +/* Filename of the C backend implementation. + * This is not inlined here because this header is included in assembly + * files as well. */ +#define MLKEM_NATIVE_ARITH_BACKEND_IMPL "aarch64/src/opt_impl.h" + +#endif /* MLKEM_NATIVE_ARITH_PROFILE_H */ diff --git a/mlkem/native/aarch64/aarch64_zetas.c b/mlkem/native/aarch64/src/aarch64_zetas.c similarity index 98% rename from mlkem/native/aarch64/aarch64_zetas.c rename to mlkem/native/aarch64/src/aarch64_zetas.c index f0a0d5546..ecf1b529a 100644 --- a/mlkem/native/aarch64/aarch64_zetas.c +++ b/mlkem/native/aarch64/src/aarch64_zetas.c @@ -8,9 +8,13 @@ * Do not modify it directly. */ -#include "arith_native_aarch64.h" +#include "common.h" + +#if defined(MLKEM_NATIVE_ARITH_BACKEND_AARCH64_CLEAN) || \ + defined(MLKEM_NATIVE_ARITH_BACKEND_AARCH64_OPT) -#ifdef MLKEM_USE_NATIVE_AARCH64 +#include +#include "arith_native_aarch64.h" /* * Table of zeta values used in the AArch64 forward NTT @@ -163,10 +167,10 @@ const int16_t aarch64_zetas_mulcache_twisted_native[] = { -11566, 11566, }; -#else /* MLKEM_USE_NATIVE_AARCH64 */ +#else #include "params.h" /* Dummy declaration for compilers disliking empty compilation units */ #define empty_cu_aarch64_zetas MLKEM_NAMESPACE(empty_cu_aarch64_zetas) int empty_cu_aarch64_zetas; -#endif /* MLKEM_USE_NATIVE_AARCH64 */ +#endif diff --git a/mlkem/native/aarch64/arith_native_aarch64.h b/mlkem/native/aarch64/src/arith_native_aarch64.h similarity index 96% rename from mlkem/native/aarch64/arith_native_aarch64.h rename to mlkem/native/aarch64/src/arith_native_aarch64.h index f39eb9ac8..2f3b0ef4f 100644 --- a/mlkem/native/aarch64/arith_native_aarch64.h +++ b/mlkem/native/aarch64/src/arith_native_aarch64.h @@ -6,10 +6,7 @@ #define MLKEM_AARCH64_NATIVE_H #include -#include "config.h" -#include "params.h" - -#ifdef MLKEM_USE_NATIVE_AARCH64 +#include "common.h" #define aarch64_ntt_zetas_layer01234 \ MLKEM_NAMESPACE(aarch64_ntt_zetas_layer01234) @@ -72,6 +69,9 @@ void poly_mulcache_compute_asm_opt(int16_t *, const int16_t *, const int16_t *, #define poly_tobytes_asm_clean MLKEM_NAMESPACE(poly_tobytes_asm_clean) void poly_tobytes_asm_clean(uint8_t *r, const int16_t *a); +#define poly_tobytes_asm_opt MLKEM_NAMESPACE(poly_tobytes_asm_opt) +void poly_tobytes_asm_opt(uint8_t *r, const int16_t *a); + #define polyvec_basemul_acc_montgomery_cached_asm_clean \ MLKEM_NAMESPACE(polyvec_basemul_acc_montgomery_cached_asm_clean) void polyvec_basemul_acc_montgomery_cached_asm_clean(int16_t *r, @@ -85,6 +85,4 @@ void polyvec_basemul_acc_montgomery_cached_asm_opt(int16_t *r, const int16_t *a, const int16_t *b, const int16_t *b_cache); - -#endif /* MLKEM_USE_NATIVE_AARCH64 */ #endif /* MLKEM_AARCH64_NATIVE_H */ diff --git a/mlkem/native/aarch64/profiles/clean.h b/mlkem/native/aarch64/src/clean_impl.h similarity index 90% rename from mlkem/native/aarch64/profiles/clean.h rename to mlkem/native/aarch64/src/clean_impl.h index e7f71bd53..0a40199e7 100644 --- a/mlkem/native/aarch64/profiles/clean.h +++ b/mlkem/native/aarch64/src/clean_impl.h @@ -5,14 +5,14 @@ /* ML-KEM arithmetic native profile for clean assembly */ -#ifdef MLKEM_ARITH_NATIVE_PROFILE_H +#ifdef MLKEM_NATIVE_ARITH_PROFILE_IMPL_H #error Only one MLKEM_ARITH assembly profile can be defined -- did you include multiple profiles? #else -#define MLKEM_ARITH_NATIVE_PROFILE_H +#define MLKEM_NATIVE_ARITH_PROFILE_IMPL_H -#include "../../arith_native.h" -#include "../arith_native_aarch64.h" +#include "arith_native_aarch64.h" +/* Set of primitives that this backend replaces */ #define MLKEM_USE_NATIVE_NTT #define MLKEM_USE_NATIVE_INTT #define MLKEM_USE_NATIVE_POLY_REDUCE @@ -22,7 +22,6 @@ #define MLKEM_USE_NATIVE_POLY_TOBYTES #define MLKEM_USE_NATIVE_REJ_UNIFORM -#define NTT_BOUND_NATIVE (6 * MLKEM_Q) static INLINE void ntt_native(poly *data) { ntt_asm_clean(data->coeffs, aarch64_ntt_zetas_layer01234, @@ -75,4 +74,4 @@ static INLINE int rej_uniform_native(int16_t *r, unsigned int len, return (int)rej_uniform_asm_clean(r, buf, buflen); } -#endif /* MLKEM_ARITH_NATIVE_PROFILE_H */ +#endif /* MLKEM_NATIVE_ARITH_PROFILE_IMPL_H */ diff --git a/mlkem/native/aarch64/common.i b/mlkem/native/aarch64/src/common.i similarity index 100% rename from mlkem/native/aarch64/common.i rename to mlkem/native/aarch64/src/common.i diff --git a/mlkem/native/aarch64/consts.h b/mlkem/native/aarch64/src/consts.h similarity index 96% rename from mlkem/native/aarch64/consts.h rename to mlkem/native/aarch64/src/consts.h index 0e834bed4..c40947299 100644 --- a/mlkem/native/aarch64/consts.h +++ b/mlkem/native/aarch64/src/consts.h @@ -7,7 +7,7 @@ #define MLKEM_NATIVE_AARCH64_CONSTS #include -#include "params.h" +#include "common.h" #define zetas_mulcache_native MLKEM_NAMESPACE(zetas_mulcache_native) extern const int16_t zetas_mulcache_native[256]; diff --git a/mlkem/native/aarch64/intt_clean.S b/mlkem/native/aarch64/src/intt_clean.S similarity index 98% rename from mlkem/native/aarch64/intt_clean.S rename to mlkem/native/aarch64/src/intt_clean.S index 2ac4e0f15..2f05d8cca 100644 --- a/mlkem/native/aarch64/intt_clean.S +++ b/mlkem/native/aarch64/src/intt_clean.S @@ -23,8 +23,8 @@ /// SOFTWARE. /// -#include "config.h" -#if defined(MLKEM_USE_NATIVE_AARCH64) +#include "common.h" +#if defined(MLKEM_NATIVE_ARITH_BACKEND_AARCH64_CLEAN) // Needed to provide ASM_LOAD directive #include "common.i" @@ -371,4 +371,4 @@ layer012_start: pop_stack ret -#endif /* MLKEM_USE_NATIVE_AARCH64 */ +#endif /* MLKEM_NATIVE_ARITH_BACKEND_AARCH64_CLEAN */ diff --git a/mlkem/native/aarch64/intt_opt.S b/mlkem/native/aarch64/src/intt_opt.S similarity index 99% rename from mlkem/native/aarch64/intt_opt.S rename to mlkem/native/aarch64/src/intt_opt.S index 48c412f36..fc720e504 100644 --- a/mlkem/native/aarch64/intt_opt.S +++ b/mlkem/native/aarch64/src/intt_opt.S @@ -23,8 +23,8 @@ /// SOFTWARE. /// -#include "config.h" -#if defined(MLKEM_USE_NATIVE_AARCH64) +#include "common.h" +#if defined(MLKEM_NATIVE_ARITH_BACKEND_AARCH64_OPT) // Needed to provide ASM_LOAD directive #include "common.i" @@ -1027,4 +1027,4 @@ layer012_start: pop_stack ret -#endif /* MLKEM_USE_NATIVE_AARCH64 */ +#endif /* MLKEM_NATIVE_ARITH_BACKEND_AARCH64_OPT */ diff --git a/mlkem/native/aarch64/ntt_clean.S b/mlkem/native/aarch64/src/ntt_clean.S similarity index 98% rename from mlkem/native/aarch64/ntt_clean.S rename to mlkem/native/aarch64/src/ntt_clean.S index 4243b9431..ad9086e27 100644 --- a/mlkem/native/aarch64/ntt_clean.S +++ b/mlkem/native/aarch64/src/ntt_clean.S @@ -24,8 +24,8 @@ /// SOFTWARE. /// -#include "config.h" -#if defined(MLKEM_USE_NATIVE_AARCH64) +#include "common.h" +#if defined(MLKEM_NATIVE_ARITH_BACKEND_AARCH64_CLEAN) // Needed to provide ASM_LOAD directive #include "common.i" @@ -295,4 +295,4 @@ layer3456_start: pop_stack ret -#endif /* MLKEM_USE_NATIVE_AARCH64 */ +#endif /* MLKEM_NATIVE_ARITH_BACKEND_AARCH64_CLEAN */ diff --git a/mlkem/native/aarch64/ntt_opt.S b/mlkem/native/aarch64/src/ntt_opt.S similarity index 99% rename from mlkem/native/aarch64/ntt_opt.S rename to mlkem/native/aarch64/src/ntt_opt.S index 71779afe9..f4cbc928f 100644 --- a/mlkem/native/aarch64/ntt_opt.S +++ b/mlkem/native/aarch64/src/ntt_opt.S @@ -24,8 +24,8 @@ /// SOFTWARE. /// -#include "config.h" -#if defined(MLKEM_USE_NATIVE_AARCH64) +#include "common.h" +#if defined(MLKEM_NATIVE_ARITH_BACKEND_AARCH64_OPT) // Needed to provide ASM_LOAD directive #include "common.i" @@ -892,4 +892,4 @@ layer3456_start: pop_stack ret -#endif /* MLKEM_USE_NATIVE_AARCH64 */ +#endif /* MLKEM_NATIVE_ARITH_BACKEND_AARCH64_OPT */ diff --git a/mlkem/native/aarch64/profiles/opt.h b/mlkem/native/aarch64/src/opt_impl.h similarity index 89% rename from mlkem/native/aarch64/profiles/opt.h rename to mlkem/native/aarch64/src/opt_impl.h index 2414700bf..bc9af0dee 100644 --- a/mlkem/native/aarch64/profiles/opt.h +++ b/mlkem/native/aarch64/src/opt_impl.h @@ -5,14 +5,14 @@ /* ML-KEM arithmetic native profile for clean assembly */ -#ifdef MLKEM_ARITH_NATIVE_PROFILE_H +#ifdef MLKEM_NATIVE_ARITH_PROFILE_IMPL_H #error Only one MLKEM_ARITH assembly profile can be defined -- did you include multiple profiles? #else -#define MLKEM_ARITH_NATIVE_PROFILE_H +#define MLKEM_NATIVE_ARITH_PROFILE_IMPL_H -#include "../../arith_native.h" -#include "../arith_native_aarch64.h" +#include "arith_native_aarch64.h" +/* Set of primitives that this backend replaces */ #define MLKEM_USE_NATIVE_NTT #define MLKEM_USE_NATIVE_INTT #define MLKEM_USE_NATIVE_POLY_REDUCE @@ -62,7 +62,7 @@ static INLINE void polyvec_basemul_acc_montgomery_cached_native( static INLINE void poly_tobytes_native(uint8_t r[MLKEM_POLYBYTES], const poly *a) { - poly_tobytes_asm_clean(r, a->coeffs); + poly_tobytes_asm_opt(r, a->coeffs); } static INLINE int rej_uniform_native(int16_t *r, unsigned int len, @@ -75,4 +75,4 @@ static INLINE int rej_uniform_native(int16_t *r, unsigned int len, return (int)rej_uniform_asm_clean(r, buf, buflen); } -#endif /* MLKEM_ARITH_NATIVE_PROFILE_H */ +#endif /* MLKEM_NATIVE_ARITH_PROFILE_IMPL_H */ diff --git a/mlkem/native/aarch64/optimize.sh b/mlkem/native/aarch64/src/optimize.sh similarity index 100% rename from mlkem/native/aarch64/optimize.sh rename to mlkem/native/aarch64/src/optimize.sh diff --git a/mlkem/native/aarch64/poly_clean.S b/mlkem/native/aarch64/src/poly_clean.S similarity index 98% rename from mlkem/native/aarch64/poly_clean.S rename to mlkem/native/aarch64/src/poly_clean.S index 86e4e494a..3e1bc5cf4 100644 --- a/mlkem/native/aarch64/poly_clean.S +++ b/mlkem/native/aarch64/src/poly_clean.S @@ -3,8 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "config.h" -#if defined(MLKEM_USE_NATIVE_AARCH64) +#include "common.h" +#if defined(MLKEM_NATIVE_ARITH_BACKEND_AARCH64_CLEAN) // Needed to provide ASM_LOAD directive #include "common.i" @@ -285,4 +285,4 @@ poly_tomont_asm_loop: ret -#endif /* MLKEM_USE_NATIVE_AARCH64 */ +#endif /* MLKEM_NATIVE_ARITH_BACKEND_AARCH64_CLEAN */ diff --git a/mlkem/native/aarch64/poly_opt.S b/mlkem/native/aarch64/src/poly_opt.S similarity index 99% rename from mlkem/native/aarch64/poly_opt.S rename to mlkem/native/aarch64/src/poly_opt.S index d86595059..df3b21008 100644 --- a/mlkem/native/aarch64/poly_opt.S +++ b/mlkem/native/aarch64/src/poly_opt.S @@ -3,8 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "config.h" -#if defined(MLKEM_USE_NATIVE_AARCH64) +#include "common.h" +#if defined(MLKEM_NATIVE_ARITH_BACKEND_AARCH64_OPT) // Needed to provide ASM_LOAD directive #include "common.i" @@ -649,4 +649,4 @@ poly_tomont_asm_loop: ret -#endif /* MLKEM_USE_NATIVE_AARCH64 */ +#endif /* MLKEM_NATIVE_ARITH_BACKEND_AARCH64_OPT */ diff --git a/mlkem/native/aarch64/polyvec_clean.S b/mlkem/native/aarch64/src/polyvec_clean.S similarity index 98% rename from mlkem/native/aarch64/polyvec_clean.S rename to mlkem/native/aarch64/src/polyvec_clean.S index 59f57d77a..bfd1d2b8a 100644 --- a/mlkem/native/aarch64/polyvec_clean.S +++ b/mlkem/native/aarch64/src/polyvec_clean.S @@ -9,8 +9,8 @@ // https://eprint.iacr.org/2021/986 // https://github.com/neon-ntt/neon-ntt -#include "config.h" -#if defined(MLKEM_USE_NATIVE_AARCH64) +#include "common.h" +#if defined(MLKEM_NATIVE_ARITH_BACKEND_AARCH64_CLEAN) #include "params.h" @@ -279,4 +279,4 @@ k4_loop_start: ret #endif /* MLKEM_K == 4 */ -#endif /* MLKEM_USE_NATIVE_AARCH64 */ +#endif /* MLKEM_NATIVE_ARITH_BACKEND_AARCH64_CLEAN */ diff --git a/mlkem/native/aarch64/polyvec_opt.S b/mlkem/native/aarch64/src/polyvec_opt.S similarity index 99% rename from mlkem/native/aarch64/polyvec_opt.S rename to mlkem/native/aarch64/src/polyvec_opt.S index 9ae035639..07dc98efd 100644 --- a/mlkem/native/aarch64/polyvec_opt.S +++ b/mlkem/native/aarch64/src/polyvec_opt.S @@ -6,12 +6,11 @@ // AArch64 re-implementation of the asymmetric base multiplication from: // Neon NTT: Faster Dilithium, Kyber, and Saber on Cortex-A72 and Apple M1 -// https: // eprint.iacr.org/2021/986 -// https: // github.com/neon-ntt/neon-ntt - -#include "config.h" -#if defined(MLKEM_USE_NATIVE_AARCH64) +// https://eprint.iacr.org/2021/986 +// https://github.com/neon-ntt/neon-ntt +#include "common.h" +#if defined(MLKEM_NATIVE_ARITH_BACKEND_AARCH64_OPT) #include "params.h" // Needed to provide ASM_LOAD directive @@ -1122,4 +1121,4 @@ k4_loop_start: ret #endif /* MLKEM_K == 4 */ -#endif /* MLKEM_USE_NATIVE_AARCH64 */ +#endif /* MLKEM_NATIVE_ARITH_BACKEND_AARCH64_OPT */ diff --git a/mlkem/native/aarch64/rej_uniform_asm_clean.S b/mlkem/native/aarch64/src/rej_uniform_asm_clean.S similarity index 99% rename from mlkem/native/aarch64/rej_uniform_asm_clean.S rename to mlkem/native/aarch64/src/rej_uniform_asm_clean.S index 00332ec65..c51e53188 100644 --- a/mlkem/native/aarch64/rej_uniform_asm_clean.S +++ b/mlkem/native/aarch64/src/rej_uniform_asm_clean.S @@ -18,9 +18,9 @@ * * Returns number of sampled 16-bit integers (at most MLKEM_N). **************************************************/ -#include "config.h" -#include "params.h" -#if defined(MLKEM_USE_NATIVE_AARCH64) +#include "common.h" +#if defined(MLKEM_NATIVE_ARITH_BACKEND_AARCH64_CLEAN) || \ + defined(MLKEM_NATIVE_ARITH_BACKEND_AARCH64_OPT) // Needed to provide ASM_LOAD directive #include "common.i" @@ -605,4 +605,5 @@ return: pop_stack ret -#endif /* MLKEM_USE_NATIVE_AARCH64 */ +#endif /* defined(MLKEM_NATIVE_ARITH_BACKEND_AARCH64_CLEAN) || + defined(MLKEM_NATIVE_ARITH_BACKEND_AARCH64_OPT) */ diff --git a/mlkem/native/arith_native.h b/mlkem/native/api.h similarity index 98% rename from mlkem/native/arith_native.h rename to mlkem/native/api.h index b7e921323..5a2d92b1d 100644 --- a/mlkem/native/arith_native.h +++ b/mlkem/native/api.h @@ -6,14 +6,12 @@ #define MLKEM_ARITH_NATIVE_H #include -#include "config.h" -#include "params.h" - -#if defined(MLKEM_USE_NATIVE) +#include "cbmc.h" #include "poly.h" #include "polyvec.h" -#include "profile.h" + +#include "common.h" /* * MLKEM native arithmetic interface @@ -246,5 +244,4 @@ static INLINE int rej_uniform_native(int16_t *r, unsigned int len, const uint8_t *buf, unsigned int buflen); #endif /* MLKEM_USE_NATIVE_REJ_UNIFORM */ -#endif /* MLKEM_USE_NATIVE */ #endif /* MLKEM_ARITH_NATIVE_H */ diff --git a/mlkem/native/default.h b/mlkem/native/default.h new file mode 100644 index 000000000..d1e41c52e --- /dev/null +++ b/mlkem/native/default.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024 The mlkem-native project authors + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef MLKEM_NATIVE_ARITH_BACKEND_DEFAULT_H +#define MLKEM_NATIVE_ARITH_BACKEND_DEFAULT_H + +/* + * Default arithmetic backend + */ +#include "sys.h" + +#ifdef SYS_AARCH64 +/* + * For AArch64, we currently we have one clean and one opt profile. + * We default to the opt profile. + * + * In the future, this may branch further depending on the microarchitecture. + */ +#include "aarch64/opt.h" +#endif /* SYS_AARCH64 */ + +#ifdef SYS_X86_64_AVX2 +/* + * For now, there's only one x86_64 profile, based on + * the AVX2 code from the Kyber repository. + * https://github.com/pq-crystals/kyber + */ +#include "x86_64/default.h" +#endif /* SYS_X86_64 */ + +#endif /* MLKEM_NATIVE_ARITH_BACKEND_DEFAULT_H */ diff --git a/mlkem/native/profile.h b/mlkem/native/profile.h deleted file mode 100644 index ab9d93aa1..000000000 --- a/mlkem/native/profile.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2024 The mlkem-native project authors - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef MLKEM_ARITH_NATIVE_PROFILE_CHOICE_H -#define MLKEM_ARITH_NATIVE_PROFILE_CHOICE_H - -#include -#include "config.h" -#include "params.h" - -#if defined(MLKEM_USE_NATIVE) -#include "poly.h" -#include "polyvec.h" - -/* - * MLKEM native arithmetic profile - * - * The profile decides which implementation(s) of the arithmetic backend to use. - * - * If you don't change anything, the default profile will be used. This profile - * picks implementations based on characteristics of your system visible to - * the compiler. - * - * If you want to pick a specific profile for your target, there are three ways - * to do so, in descending order of convenience to the user: - * 1. Pick one of the profiles shipped with this repository. - * 2. Provide your own profile and register it via MLKEM_ARITH_NATIVE_PROFILE - * (which must be the profile's path relative to this directoru). - * 3. Set MLKEM_ARITH_NATIVE_MANUAL and use an adhoc profile specified via - * CFLAGS. - */ - -/* Option 2: Manually written profile */ -#if defined(MLKEM_ARITH_NATIVE_PROFILE) - -#define STRINGIFY_(x) #x -#define STRINGIFY(x) STRINGIFY_(x) -#include STRINGIFY(MLKEM_ARITH_NATIVE_PROFILE) - -/* Option 1: Choose from shipped list of profiles */ -#elif !defined(MLKEM_ARITH_NATIVE_MANUAL) - -#ifdef SYS_AARCH64 -/* - * For now, we only have clean and opt profiles. - * In the future, this is likely to branch further depending - * on the microarchitecture. - */ -#if defined(MLKEM_USE_NATIVE_AARCH64_CLEAN) -#include "aarch64/profiles/clean.h" -#else /* MLKEM_USE_NATIVE_AARCH64_CLEAN */ -#include "aarch64/profiles/opt.h" -#endif /* !MLKEM_USE_NATIVE_AARCH64_CLEAN */ -#endif /* SYS_AARCH64 */ - -#ifdef SYS_X86_64_AVX2 -/* - * For now, there's only one x86_64 profile, which is essentially - * the AVX2 code from the Kyber repository - * https://github.com/pq-crystals/kyber - */ -#include "x86_64/profiles/default.h" -#endif /* SYS_X86_64 */ - -#else /* !MLKEM_ARITH_NATIVE_PROFILE && MLKEM_ARITH_NATIVE_MANUAL */ - -/* Option 3: Build your own profile here, or via CFLAGS */ - -#endif /* !MLKEM_ARITH_NATIVE_PROFILE && !MLKEM_ARITH_NATIVE_MANUAL */ - -#endif /* MLKEM_USE_NATIVE */ -#endif /* MLKEM_ARITH_NATIVE_PROFILE_CHOICE_H */ diff --git a/mlkem/native/x86_64/default.h b/mlkem/native/x86_64/default.h new file mode 100644 index 000000000..592e8996d --- /dev/null +++ b/mlkem/native/x86_64/default.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024 The mlkem-native project authors + * SPDX-License-Identifier: Apache-2.0 + */ + +/* ML-KEM arithmetic native profile for clean assembly */ + +#ifdef MLKEM_NATIVE_ARITH_PROFILE_H +#error Only one MLKEM_ARITH assembly profile can be defined -- did you include multiple profiles? +#else +#define MLKEM_NATIVE_ARITH_PROFILE_H + +/* Identifier for this backend so that source and assembly files + * in the build can be appropriately guarded. */ +#define MLKEM_NATIVE_ARITH_BACKEND_X86_64_DEFAULT + +#define MLKEM_NATIVE_ARITH_BACKEND_NAME X86_64_DEFAULT + +/* Filename of the C backend implementation. + * This is not inlined here because this header is included in assembly + * files as well. */ +#define MLKEM_NATIVE_ARITH_BACKEND_IMPL "x86_64/src/default_impl.h" + +#endif /* MLKEM_NATIVE_ARITH_PROFILE_H */ diff --git a/mlkem/native/x86_64/align.h b/mlkem/native/x86_64/src/align.h similarity index 100% rename from mlkem/native/x86_64/align.h rename to mlkem/native/x86_64/src/align.h diff --git a/mlkem/native/x86_64/arith_native_x86_64.h b/mlkem/native/x86_64/src/arith_native_x86_64.h similarity index 91% rename from mlkem/native/x86_64/arith_native_x86_64.h rename to mlkem/native/x86_64/src/arith_native_x86_64.h index b346e1eb2..4b78c004a 100644 --- a/mlkem/native/x86_64/arith_native_x86_64.h +++ b/mlkem/native/x86_64/src/arith_native_x86_64.h @@ -5,16 +5,13 @@ #ifndef MLKEM_X86_64_NATIVE_H #define MLKEM_X86_64_NATIVE_H -#include -#include "config.h" -#include "fips202.h" -#include "params.h" -#include "polyvec.h" - -#if defined(MLKEM_USE_NATIVE_X86_64) && defined(SYS_X86_64_AVX2) +#include "common.h" #include #include +#include "consts.h" +#include "fips202.h" +#include "polyvec.h" #define REJ_UNIFORM_AVX_NBLOCKS \ ((12 * MLKEM_N / 8 * (1 << 12) / MLKEM_Q + SHAKE128_RATE) / SHAKE128_RATE) @@ -57,6 +54,4 @@ void nttfrombytes_avx2(__m256i *r, const uint8_t *a, const __m256i *qdata); #define tomont_avx2 MLKEM_NAMESPACE(tomont_avx2) void tomont_avx2(__m256i *r, const __m256i *qdata); -#endif /* MLKEM_USE_NATIVE_X86_64 && SYS_X86_64_AVX2 */ - #endif /* MLKEM_X86_64_NATIVE_H */ diff --git a/mlkem/native/x86_64/basemul.S b/mlkem/native/x86_64/src/basemul.S similarity index 96% rename from mlkem/native/x86_64/basemul.S rename to mlkem/native/x86_64/src/basemul.S index 797b0f46a..503fbeb51 100644 --- a/mlkem/native/x86_64/basemul.S +++ b/mlkem/native/x86_64/src/basemul.S @@ -6,9 +6,8 @@ // Implementation from Kyber reference repository // https://github.com/pq-crystals/kyber/blob/main/avx2 -#include "config.h" - -#if defined(MLKEM_USE_NATIVE_X86_64) && defined(SYS_X86_64_AVX2) +#include "common.h" +#if defined(MLKEM_NATIVE_ARITH_BACKEND_X86_64_DEFAULT) #include "consts.h" #include "params.h" @@ -135,4 +134,4 @@ schoolbook 3 mov %r8,%rsp ret -#endif /* MLKEM_USE_NATIVE_X86_64 && SYS_X86_64_AVX2 */ +#endif /* MLKEM_NATIVE_ARITH_BACKEND_X86_64_DEFAULT */ diff --git a/mlkem/native/x86_64/basemul.c b/mlkem/native/x86_64/src/basemul.c similarity index 90% rename from mlkem/native/x86_64/basemul.c rename to mlkem/native/x86_64/src/basemul.c index c9dba813f..3f1653ed3 100644 --- a/mlkem/native/x86_64/basemul.c +++ b/mlkem/native/x86_64/src/basemul.c @@ -3,15 +3,16 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "config.h" +#include "common.h" -#if defined(MLKEM_USE_NATIVE_X86_64) && defined(SYS_X86_64_AVX2) +#if defined(MLKEM_NATIVE_ARITH_BACKEND_X86_64_DEFAULT) -#include "arith_native_x86_64.h" #include "consts.h" #include "poly.h" #include "polyvec.h" +#include "arith_native_x86_64.h" + static void poly_basemul_montgomery_avx2(poly *r, const poly *a, const poly *b) { basemul_avx2((__m256i *)r->coeffs, (const __m256i *)a->coeffs, @@ -57,12 +58,11 @@ void polyvec_basemul_acc_montgomery_cached_avx2(poly *r, const polyvec *a, } } -#else -#include "params.h" +#else /* MLKEM_NATIVE_ARITH_BACKEND_X86_64_DEFAULT */ /* Dummy constant to keep compiler happy despite empty CU */ #define empty_cu_avx2_basemul MLKEM_NAMESPACE(empty_cu_avx2_basemul) int empty_cu_avx2_basemul; -#endif /* MLKEM_USE_NATIVE_X86_64 && SYS_X86_64_AVX2 */ +#endif /* MLKEM_NATIVE_ARITH_BACKEND_X86_64_DEFAULT */ diff --git a/mlkem/native/x86_64/consts.c b/mlkem/native/x86_64/src/consts.c similarity index 92% rename from mlkem/native/x86_64/consts.c rename to mlkem/native/x86_64/src/consts.c index 573eabb64..9b6d0993e 100644 --- a/mlkem/native/x86_64/consts.c +++ b/mlkem/native/x86_64/src/consts.c @@ -8,13 +8,12 @@ * https://github.com/pq-crystals/kyber/blob/main/avx2/consts.c */ -#include "config.h" +#include "common.h" -#if defined(MLKEM_USE_NATIVE_X86_64) && defined(SYS_X86_64_AVX2) +#if defined(MLKEM_NATIVE_ARITH_BACKEND_X86_64_DEFAULT) #include "align.h" #include "consts.h" -#include "params.h" #define Q MLKEM_Q #define MONT -1044 /* 2^16 mod q */ @@ -86,10 +85,9 @@ const qdata_t qdata = {{ SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT}}; -#else /* MLKEM_USE_NATIVE_X86_64 && SYS_X86_64_AVX2 */ -#include "params.h" +#else /* MLKEM_NATIVE_ARITH_BACKEND_X86_64_DEFAULT */ /* Dummy declaration for compilers disliking empty compilation units */ #define empty_cu_consts MLKEM_NAMESPACE(empty_cu_consts) int empty_cu_consts; -#endif /* MLKEM_USE_NATIVE_X86_64 && SYS_X86_64_AVX2 */ +#endif /* MLKEM_NATIVE_ARITH_BACKEND_X86_64_DEFAULT */ diff --git a/mlkem/native/x86_64/consts.h b/mlkem/native/x86_64/src/consts.h similarity index 97% rename from mlkem/native/x86_64/consts.h rename to mlkem/native/x86_64/src/consts.h index 8ca98bbf8..a9f0c484f 100644 --- a/mlkem/native/x86_64/consts.h +++ b/mlkem/native/x86_64/src/consts.h @@ -11,7 +11,7 @@ #ifndef CONSTS_H #define CONSTS_H -#include "params.h" +#include "common.h" #define _16XQ 0 #define _16XQINV 16 diff --git a/mlkem/native/x86_64/profiles/default.h b/mlkem/native/x86_64/src/default_impl.h similarity index 92% rename from mlkem/native/x86_64/profiles/default.h rename to mlkem/native/x86_64/src/default_impl.h index 55eb0ad01..4f3cd2c9a 100644 --- a/mlkem/native/x86_64/profiles/default.h +++ b/mlkem/native/x86_64/src/default_impl.h @@ -5,17 +5,14 @@ /* ML-KEM arithmetic native profile for clean assembly */ -#ifdef MLKEM_ARITH_NATIVE_PROFILE_H +#ifdef MLKEM_NATIVE_ARITH_PROFILE_IMPL_H #error Only one MLKEM_ARITH assembly profile can be defined -- did you include multiple profiles? #else -#define MLKEM_ARITH_NATIVE_PROFILE_H +#define MLKEM_NATIVE_ARITH_PROFILE_IMPL_H #include -#include "../../arith_native.h" -#include "../arith_native_x86_64.h" -#include "../consts.h" - +#include "arith_native_x86_64.h" #include "poly.h" #define MLKEM_USE_NATIVE_NTT_CUSTOM_ORDER @@ -96,4 +93,4 @@ static INLINE void poly_frombytes_native(poly *r, nttfrombytes_avx2((__m256i *)r->coeffs, a, qdata.vec); } -#endif /* MLKEM_ARITH_NATIVE_PROFILE_H */ +#endif /* MLKEM_NATIVE_ARITH_PROFILE_IMPL_H */ diff --git a/mlkem/native/x86_64/fq.S b/mlkem/native/x86_64/src/fq.S similarity index 91% rename from mlkem/native/x86_64/fq.S rename to mlkem/native/x86_64/src/fq.S index 00fb093c5..50ef190b7 100644 --- a/mlkem/native/x86_64/fq.S +++ b/mlkem/native/x86_64/src/fq.S @@ -11,13 +11,12 @@ // in [0,1,...,q-1] rather than [0,1,...,q], matching the // semantics of poly_reduce(). -#include "config.h" -#include "params.h" +#include "common.h" -#if defined(MLKEM_USE_NATIVE_X86_64) && defined(SYS_X86_64_AVX2) +#if defined(MLKEM_NATIVE_ARITH_BACKEND_X86_64_DEFAULT) #include "consts.h" -.include "fq.inc" +#include "fq.inc" .text reduce128_avx2: @@ -115,4 +114,4 @@ add $256,%rdi call tomont128_avx2 ret -#endif /* MLKEM_USE_NATIVE_X86_64 && SYS_X86_64_AVX2 */ +#endif /* MLKEM_NATIVE_ARITH_BACKEND_X86_64_DEFAULT */ diff --git a/mlkem/native/x86_64/fq.inc b/mlkem/native/x86_64/src/fq.inc similarity index 100% rename from mlkem/native/x86_64/fq.inc rename to mlkem/native/x86_64/src/fq.inc diff --git a/mlkem/native/x86_64/intt.S b/mlkem/native/x86_64/src/intt.S similarity index 97% rename from mlkem/native/x86_64/intt.S rename to mlkem/native/x86_64/src/intt.S index 8418cc471..4860985ed 100644 --- a/mlkem/native/x86_64/intt.S +++ b/mlkem/native/x86_64/src/intt.S @@ -8,14 +8,15 @@ * * Changes to placement of modular reductions have * been made to simplify reasoning of non-overflow */ -#include "config.h" -#if defined(MLKEM_USE_NATIVE_X86_64) && defined(SYS_X86_64_AVX2) +#include "common.h" + +#if defined(MLKEM_NATIVE_ARITH_BACKEND_X86_64_DEFAULT) #include "consts.h" #include "params.h" -.include "shuffle.inc" -.include "fq.inc" +#include "shuffle.inc" +#include "fq.inc" /* Compute four GS butterflies between rh{0,1,2,3} and rl{0,1,2,3}. * Butterflies 0,1 use root zh0 and twisted root zl0, and butterflies @@ -252,4 +253,4 @@ intt_level6 0 intt_level6 1 ret -#endif /* MLKEM_USE_NATIVE_X86_64 && SYS_X86_64_AVX2 */ +#endif /* MLKEM_NATIVE_ARITH_BACKEND_X86_64_DEFAULT */ diff --git a/mlkem/native/x86_64/ntt.S b/mlkem/native/x86_64/src/ntt.S similarity index 97% rename from mlkem/native/x86_64/ntt.S rename to mlkem/native/x86_64/src/ntt.S index f159faf4f..a0b6f734c 100644 --- a/mlkem/native/x86_64/ntt.S +++ b/mlkem/native/x86_64/src/ntt.S @@ -6,14 +6,13 @@ // Implementation from Kyber reference repository // https://github.com/pq-crystals/kyber/blob/main/avx2 -#include "config.h" - -#if defined(MLKEM_USE_NATIVE_X86_64) && defined(SYS_X86_64_AVX2) +#include "common.h" +#if defined(MLKEM_NATIVE_ARITH_BACKEND_X86_64_DEFAULT) #include "consts.h" #include "params.h" -.include "shuffle.inc" +#include "shuffle.inc" /* Compute steps 1,2 / 3 of Montgomery multiplication */ .macro mul rh0,rh1,rh2,rh3,zl0=15,zl1=15,zh0=2,zh1=2 @@ -219,4 +218,4 @@ levels1t6 1 ret -#endif /* MLKEM_USE_NATIVE_X86_64 && SYS_X86_64_AVX2 */ +#endif /* MLKEM_NATIVE_ARITH_BACKEND_X86_64_DEFAULT */ diff --git a/mlkem/native/x86_64/rej_uniform_avx2.c b/mlkem/native/x86_64/src/rej_uniform_avx2.c similarity index 98% rename from mlkem/native/x86_64/rej_uniform_avx2.c rename to mlkem/native/x86_64/src/rej_uniform_avx2.c index c6e663f7d..c3c8b8104 100644 --- a/mlkem/native/x86_64/rej_uniform_avx2.c +++ b/mlkem/native/x86_64/src/rej_uniform_avx2.c @@ -8,18 +8,15 @@ * https://github.com/pq-crystals/kyber/blob/main/avx2 */ -#include "config.h" +#include "common.h" -#if defined(MLKEM_USE_NATIVE_X86_64) && defined(SYS_X86_64_AVX2) - -#include "arith_native_x86_64.h" +#if defined(MLKEM_NATIVE_ARITH_BACKEND_X86_64_DEFAULT) #include #include #include +#include "arith_native_x86_64.h" #include "consts.h" -#include "params.h" - /* #define BMI */ #ifndef BMI @@ -290,10 +287,9 @@ unsigned int rej_uniform_avx2(int16_t *RESTRICT r, const uint8_t *buf) return ctr; } -#else /* MLKEM_USE_NATIVE_X86_64 && SYS_X86_64_AVX2 */ -#include "params.h" +#else /* MLKEM_NATIVE_ARITH_BACKEND_X86_64_DEFAULT */ /* Dummy declaration for compilers disliking empty compilation units */ #define empty_cu_rej_uniform_avx2 MLKEM_NAMESPACE(empty_cu_rej_uniform_avx2) int empty_cu_rej_uniform_avx2; -#endif /* MLKEM_USE_NATIVE_X86_64 && SYS_X86_64_AVX2 */ +#endif /* MLKEM_NATIVE_ARITH_BACKEND_X86_64_DEFAULT */ diff --git a/mlkem/native/x86_64/shuffle.S b/mlkem/native/x86_64/src/shuffle.S similarity index 96% rename from mlkem/native/x86_64/shuffle.S rename to mlkem/native/x86_64/src/shuffle.S index dd1243121..34f6b30b0 100644 --- a/mlkem/native/x86_64/shuffle.S +++ b/mlkem/native/x86_64/src/shuffle.S @@ -6,14 +6,14 @@ // Implementation from Kyber reference repository // https://github.com/pq-crystals/kyber/blob/main/avx2 -#include "config.h" +#include "common.h" -#if defined(MLKEM_USE_NATIVE_X86_64) && defined(SYS_X86_64_AVX2) +#if defined(MLKEM_NATIVE_ARITH_BACKEND_X86_64_DEFAULT) #include "consts.h" #include "params.h" -.include "fq.inc" -.include "shuffle.inc" +#include "fq.inc" +#include "shuffle.inc" .global MLKEM_NAMESPACE(nttpack_avx2) MLKEM_NAMESPACE(nttpack_avx2): @@ -255,4 +255,4 @@ add $192,%rsi call nttfrombytes128_avx ret -#endif /* MLKEM_USE_NATIVE_X86_64 && SYS_X86_64_AVX2 */ +#endif /* MLKEM_NATIVE_ARITH_BACKEND_X86_64_DEFAULT */ diff --git a/mlkem/native/x86_64/shuffle.inc b/mlkem/native/x86_64/src/shuffle.inc similarity index 100% rename from mlkem/native/x86_64/shuffle.inc rename to mlkem/native/x86_64/src/shuffle.inc diff --git a/mlkem/native/x86_64/x86_64_zetas.i b/mlkem/native/x86_64/src/x86_64_zetas.i similarity index 100% rename from mlkem/native/x86_64/x86_64_zetas.i rename to mlkem/native/x86_64/src/x86_64_zetas.i diff --git a/mlkem/ntt.c b/mlkem/ntt.c index 8de1c5446..178e8467c 100644 --- a/mlkem/ntt.c +++ b/mlkem/ntt.c @@ -2,14 +2,12 @@ * Copyright (c) 2024 The mlkem-native project authors * SPDX-License-Identifier: Apache-2.0 */ -#include "ntt.h" #include -#include "params.h" -#include "reduce.h" -#include "arith_native.h" +#include "arith_backend.h" #include "debug/debug.h" #include "ntt.h" +#include "reduce.h" #if !defined(MLKEM_USE_NATIVE_NTT) /* diff --git a/mlkem/ntt.h b/mlkem/ntt.h index 68c9e6724..efa38ecc9 100644 --- a/mlkem/ntt.h +++ b/mlkem/ntt.h @@ -6,9 +6,8 @@ #define NTT_H #include -#include "arith_native.h" #include "cbmc.h" -#include "params.h" +#include "common.h" #include "poly.h" #include "reduce.h" diff --git a/mlkem/params.h b/mlkem/params.h index 85797f067..586c31d33 100644 --- a/mlkem/params.h +++ b/mlkem/params.h @@ -5,47 +5,12 @@ #ifndef PARAMS_H #define PARAMS_H -#include "common.h" #include "config.h" -#include "cpucap.h" -#ifndef MLKEM_K -#define MLKEM_K 3 /* Change this for different security strengths */ +#if !defined(MLKEM_K) +#error MLKEM_K is not defined #endif -#if defined(MLKEM_USE_NATIVE_X86_64) -#define MLKEM_NATIVE_BACKEND X86_64 -#elif defined(MLKEM_USE_NATIVE_AARCH64) -#define MLKEM_NATIVE_BACKEND AARCH64 -#else -#define MLKEM_NATIVE_BACKEND C -#endif - -/* Don't change parameters below this line */ -#if (MLKEM_K == 2) -#define MLKEM_PARAM_NAME MLKEM512 -#elif (MLKEM_K == 3) -#define MLKEM_PARAM_NAME MLKEM768 -#elif (MLKEM_K == 4) -#define MLKEM_PARAM_NAME MLKEM1024 -#else -#error "MLKEM_K must be in {2,3,4}" -#endif - -#define ___MLKEM_NAMESPACE(x1, x2, x3, x4) x1##_##x2##_##x3##_##x4 -#define __MLKEM_NAMESPACE(x1, x2, x3, x4) ___MLKEM_NAMESPACE(x1, x2, x3, x4) - -/* - * NAMESPACE is PQCP_MLKEM_NATIVE___ - * e.g., PQCP_MLKEM_NATIVE_MLKEM512_AARCH64_ - */ -#define MLKEM_NAMESPACE(s) \ - __MLKEM_NAMESPACE(PQCP_MLKEM_NATIVE, MLKEM_PARAM_NAME, MLKEM_NATIVE_BACKEND, \ - s) -#define _MLKEM_NAMESPACE(s) \ - __MLKEM_NAMESPACE(_PQCP_MLKEM_NATIVE, MLKEM_PARAM_NAME, \ - MLKEM_NATIVE_BACKEND, s) - #define MLKEM_N 256 #define MLKEM_Q 3329 #define UINT12_MAX 4095 diff --git a/mlkem/poly.c b/mlkem/poly.c index fdc0ef4af..db7d64ebf 100644 --- a/mlkem/poly.c +++ b/mlkem/poly.c @@ -2,21 +2,20 @@ * Copyright (c) 2024 The mlkem-native project authors * SPDX-License-Identifier: Apache-2.0 */ -#include "poly.h" #include #include + +#include "arith_backend.h" #include "cbd.h" #include "cbmc.h" +#include "debug/debug.h" #include "fips202x4.h" #include "ntt.h" -#include "params.h" +#include "poly.h" #include "reduce.h" #include "symmetric.h" #include "verify.h" -#include "arith_native.h" -#include "debug/debug.h" - void poly_compress_du(uint8_t r[MLKEM_POLYCOMPRESSEDBYTES_DU], const poly *a) { int j; diff --git a/mlkem/poly.h b/mlkem/poly.h index 6d119539d..19cf7b96b 100644 --- a/mlkem/poly.h +++ b/mlkem/poly.h @@ -8,7 +8,7 @@ #include #include #include "cbmc.h" -#include "params.h" +#include "common.h" #include "reduce.h" #include "verify.h" diff --git a/mlkem/polyvec.c b/mlkem/polyvec.c index 7f268ee50..72277a626 100644 --- a/mlkem/polyvec.c +++ b/mlkem/polyvec.c @@ -4,10 +4,9 @@ */ #include "polyvec.h" #include -#include "arith_native.h" +#include "arith_backend.h" #include "config.h" #include "ntt.h" -#include "params.h" #include "poly.h" #include "debug/debug.h" diff --git a/mlkem/polyvec.h b/mlkem/polyvec.h index a4a03bf6d..cd90734fa 100644 --- a/mlkem/polyvec.h +++ b/mlkem/polyvec.h @@ -6,7 +6,7 @@ #define POLYVEC_H #include -#include "params.h" +#include "common.h" #include "poly.h" typedef struct diff --git a/mlkem/reduce.h b/mlkem/reduce.h index 39e85588a..515f706fa 100644 --- a/mlkem/reduce.h +++ b/mlkem/reduce.h @@ -7,8 +7,8 @@ #include #include "cbmc.h" +#include "common.h" #include "debug/debug.h" -#include "params.h" #define HALF_Q ((MLKEM_Q + 1) / 2) /* 1665 */ diff --git a/mlkem/rej_uniform.c b/mlkem/rej_uniform.c index 4e8a5ce9b..88102b4d7 100644 --- a/mlkem/rej_uniform.c +++ b/mlkem/rej_uniform.c @@ -2,10 +2,9 @@ * Copyright (c) 2024 The mlkem-native project authors * SPDX-License-Identifier: Apache-2.0 */ -#include "params.h" -#include "arith_native.h" #include "rej_uniform.h" +#include "arith_backend.h" /************************************************* * Name: rej_uniform_scalar diff --git a/mlkem/rej_uniform.h b/mlkem/rej_uniform.h index 7b86fa63e..e422f73cf 100644 --- a/mlkem/rej_uniform.h +++ b/mlkem/rej_uniform.h @@ -8,7 +8,7 @@ #include #include #include "cbmc.h" -#include "params.h" +#include "common.h" #define rej_uniform MLKEM_NAMESPACE(rej_uniform) /************************************************* diff --git a/mlkem/symmetric.h b/mlkem/symmetric.h index 4eb6aaba6..55ebbbd53 100644 --- a/mlkem/symmetric.h +++ b/mlkem/symmetric.h @@ -7,11 +7,9 @@ #include #include -#include "params.h" - -#include "fips202.h" - #include "cbmc.h" +#include "common.h" +#include "fips202.h" /* Macros denoting FIPS-203 specific Hash functions */ diff --git a/mlkem/sys/cpucap.h b/mlkem/sys.h similarity index 53% rename from mlkem/sys/cpucap.h rename to mlkem/sys.h index 7c3a1cdec..be3070dc2 100644 --- a/mlkem/sys/cpucap.h +++ b/mlkem/sys.h @@ -2,9 +2,8 @@ * Copyright (c) 2024 The mlkem-native project authors * SPDX-License-Identifier: Apache-2.0 */ - -#ifndef CPUCAP_H -#define CPUCAP_H +#ifndef MLKEM_NATIVE_SYS_H +#define MLKEM_NATIVE_SYS_H /* Check if we're running on an AArch64 little endian system. _M_ARM64 is set by * MSVC. */ @@ -52,4 +51,56 @@ #error "FORCE_X86_64 is set, but we don't seem to be on an X86_64 system." #endif +/* + * C90 does not have the inline compiler directive yet. + * We don't use it in C90 builds. + * However, in that case the compiler warns about some inline functions in + * header files not being used in every compilation unit that includes that + * header. To work around it we silence that warning in that case using + * __attribute__((unused)). + */ + +/* Do not use inline for C90 builds*/ +#if !defined(inline) +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#define INLINE inline +#define ALWAYS_INLINE __attribute__((always_inline)) +#elif defined(_MSC_VER) +#define INLINE __inline +#define ALWAYS_INLINE __forceinline +#else +#define INLINE __attribute__((unused)) +#define ALWAYS_INLINE +#endif + +#else +#define INLINE inline +#define ALWAYS_INLINE __attribute__((always_inline)) +#endif + +/* + * C90 does not have the restrict compiler directive yet. + * We don't use it in C90 builds. + */ +#if !defined(restrict) +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#define RESTRICT restrict +#else +#define RESTRICT +#endif + +#else + +#define RESTRICT restrict +#endif + +#define DEFAULT_ALIGN 32 +#if defined(_WIN32) +#define ALIGN __declspec(align(DEFAULT_ALIGN)) +#define asm __asm +#else +#define asm __asm__ +#define ALIGN __attribute__((aligned(DEFAULT_ALIGN))) #endif + +#endif /* MLKEM_NATIVE_SYS_H */ diff --git a/mlkem/sys/config.h b/mlkem/sys/config.h deleted file mode 100644 index 370a141a6..000000000 --- a/mlkem/sys/config.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2024 The mlkem-native project authors - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef CONFIG_H -#define CONFIG_H - -#include "cpucap.h" - -#if defined(MLKEM_USE_NATIVE) - -#if defined(SYS_AARCH64) -#define MLKEM_USE_NATIVE_AARCH64 -#endif /* SYS_AARCH64 */ - -#if defined(SYS_X86_64) -#define MLKEM_USE_NATIVE_X86_64 -#endif /* SYS_X86_64 */ - -#endif /* MLKEM_USE_NATIVE */ -#endif /* CONFIG_H */ diff --git a/mlkem/verify.c b/mlkem/verify.c index e616a8bab..b7078fcc1 100644 --- a/mlkem/verify.c +++ b/mlkem/verify.c @@ -13,7 +13,6 @@ volatile uint64_t ct_opt_blocker_u64 = 0; #else /* MLKEM_USE_ASM_VALUE_BARRIER */ -#include "params.h" #define empty_cu_verify MLKEM_NAMESPACE(empty_cu_verify) int empty_cu_verify; diff --git a/scripts/autogenerate_files.py b/scripts/autogenerate_files.py index a33d3cdfe..70d37d905 100644 --- a/scripts/autogenerate_files.py +++ b/scripts/autogenerate_files.py @@ -295,9 +295,13 @@ def gen_aarch64_mulcache_twiddles_twisted(): def gen_aarch64_fwd_ntt_zeta_file(dry_run=False): def gen(): yield from gen_header() - yield '#include "arith_native_aarch64.h"' + yield '#include "common.h"' + yield "" + yield "#if defined(MLKEM_NATIVE_ARITH_BACKEND_AARCH64_CLEAN) || \\" + yield " defined(MLKEM_NATIVE_ARITH_BACKEND_AARCH64_OPT)" yield "" - yield "#ifdef MLKEM_USE_NATIVE_AARCH64" + yield "#include " + yield '#include "arith_native_aarch64.h"' yield "" yield "/*" yield " * Table of zeta values used in the AArch64 forward NTT" @@ -327,17 +331,17 @@ def gen(): yield from map(lambda t: str(t) + ",", gen_aarch64_mulcache_twiddles_twisted()) yield "};" yield "" - yield "#else /* MLKEM_USE_NATIVE_AARCH64 */" + yield "#else" yield '#include "params.h"' yield "" yield "/* Dummy declaration for compilers disliking empty compilation units */" yield "#define empty_cu_aarch64_zetas MLKEM_NAMESPACE(empty_cu_aarch64_zetas)" yield "int empty_cu_aarch64_zetas;" - yield "#endif /* MLKEM_USE_NATIVE_AARCH64 */" + yield "#endif" yield "" update_file( - "mlkem/native/aarch64/aarch64_zetas.c", "\n".join(gen()), dry_run=dry_run + "mlkem/native/aarch64/src/aarch64_zetas.c", "\n".join(gen()), dry_run=dry_run ) @@ -414,7 +418,9 @@ def gen(): yield from map(lambda t: str(t) + ",", gen_avx2_fwd_ntt_zetas()) yield "" - update_file("mlkem/native/x86_64/x86_64_zetas.i", "\n".join(gen()), dry_run=dry_run) + update_file( + "mlkem/native/x86_64/src/x86_64_zetas.i", "\n".join(gen()), dry_run=dry_run + ) def _main(): diff --git a/scripts/ci/lint b/scripts/ci/lint index 406f00526..879ad13b2 100755 --- a/scripts/ci/lint +++ b/scripts/ci/lint @@ -85,7 +85,7 @@ check-spdx() success=false fi done - for file in $(git ls-files -- "*.[chsS]" "*.py" ":/!cbmc/*.py" ":/!examples/bring_your_own_fips202/custom_fips202/tiny_sha3/*"); do + for file in $(git ls-files -- "*.[chsS]" "*.py" ":/!cbmc/*.py" ":/!examples/bring_your_own_fips202/custom_fips202/tiny_sha3/*" ":/!examples/custom_backend/mlkem_native/fips202/native/custom/src/*"); do # Ignore symlinks if [[ ! -L $file && $(grep "Copyright (c) 2024 The mlkem-native project authors" $file | wc -l) == 0 ]]; then echo "::error file=$file,line=${line:-1},title=Missing copyright header error::$file is missing copyright header" diff --git a/scripts/lib/mlkem_test.py b/scripts/lib/mlkem_test.py index 796c4953a..73d24122a 100644 --- a/scripts/lib/mlkem_test.py +++ b/scripts/lib/mlkem_test.py @@ -98,9 +98,7 @@ def dict2str(dict): f"{self.test_type}", ] + extra_make_args - make_envs = ( - {"CFLAGS": f"{self.cflags}"} if self.cflags is not None else {} - ) | ( + make_envs = ({"CFLAGS": self.cflags} if self.cflags is not None else {}) | ( {"ARCH_FLAGS": f"{self.arch_flags}"} if self.arch_flags is not None else {} ) extra_make_envs.update(make_envs) diff --git a/test/bench_components_mlkem.c b/test/bench_components_mlkem.c index c922cb76d..b3956171c 100644 --- a/test/bench_components_mlkem.c +++ b/test/bench_components_mlkem.c @@ -12,7 +12,7 @@ #include "randombytes.h" #include "rej_uniform.h" -#include "../mlkem/native/arith_native.h" +#include "../mlkem/arith_backend.h" #include "fips202.h" #include "indcpa.h" #include "keccakf1600.h" @@ -184,7 +184,7 @@ static int bench(void) BENCH("gen_matrix", gen_matrix((polyvec *)data0, (uint8_t *)data1, 0)) -#if defined(MLKEM_USE_NATIVE_AARCH64) +#if defined(MLKEM_NATIVE_ARITH_BACKEND_AARCH64_CLEAN) BENCH("ntt-clean", ntt_asm_clean((int16_t *)data0, (int16_t *)data1, (int16_t *)data2)); BENCH("intt-clean", @@ -200,7 +200,9 @@ static int bench(void) polyvec_basemul_acc_montgomery_cached_asm_clean( (int16_t *)data0, (int16_t *)data1, (int16_t *)data2, (int16_t *)data3)); +#endif /* MLKEM_NATIVE_ARITH_BACKEND_AARCH64_CLEAN */ +#if defined(MLKEM_NATIVE_ARITH_BACKEND_AARCH64_OPT) BENCH("ntt-opt", ntt_asm_opt((int16_t *)data0, (int16_t *)data1, (int16_t *)data2)); BENCH("intt-opt", @@ -214,7 +216,7 @@ static int bench(void) polyvec_basemul_acc_montgomery_cached_asm_opt( (int16_t *)data0, (int16_t *)data1, (int16_t *)data2, (int16_t *)data3)); -#endif +#endif /* MLKEM_NATIVE_ARITH_BACKEND_AARCH64_OPT */ return 0; }